]> git.lizzy.rs Git - minetest-m13.git/blob - src/server.cpp
8dc8dbdd5968d6e1efc0c5e88bbce4abb04a66bd
[minetest-m13.git] / src / server.cpp
1 /*
2 Minetest-m13
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                         HandlePlayerHP(player, 0);
1274
1275                         /*
1276                                 Send player inventories and HPs if necessary
1277                         */
1278                         if(player->m_inventory_not_sent){
1279                                 UpdateCrafting(player->peer_id);
1280                                 SendInventory(player->peer_id);
1281                         }
1282                         if(player->m_hp_not_sent){
1283                                 SendPlayerHP(player);
1284                         }
1285
1286                         /*
1287                                 Add to environment if is not in respawn screen
1288                         */
1289                         if(!player->m_is_in_environment && !player->m_respawn_active){
1290                                 player->m_removed = false;
1291                                 player->setId(0);
1292                                 m_env->addActiveObject(player);
1293                         }
1294                 }
1295         }
1296         
1297         /* Transform liquids */
1298         m_liquid_transform_timer += dtime;
1299         if(m_liquid_transform_timer >= 1.00)
1300         {
1301                 m_liquid_transform_timer -= 1.00;
1302                 
1303                 JMutexAutoLock lock(m_env_mutex);
1304
1305                 ScopeProfiler sp(g_profiler, "Server: liquid transform");
1306
1307                 core::map<v3s16, MapBlock*> modified_blocks;
1308                 m_env->getMap().transformLiquids(modified_blocks);
1309 #if 0           
1310                 /*
1311                         Update lighting
1312                 */
1313                 core::map<v3s16, MapBlock*> lighting_modified_blocks;
1314                 ServerMap &map = ((ServerMap&)m_env->getMap());
1315                 map.updateLighting(modified_blocks, lighting_modified_blocks);
1316                 
1317                 // Add blocks modified by lighting to modified_blocks
1318                 for(core::map<v3s16, MapBlock*>::Iterator
1319                                 i = lighting_modified_blocks.getIterator();
1320                                 i.atEnd() == false; i++)
1321                 {
1322                         MapBlock *block = i.getNode()->getValue();
1323                         modified_blocks.insert(block->getPos(), block);
1324                 }
1325 #endif
1326                 /*
1327                         Set the modified blocks unsent for all the clients
1328                 */
1329                 
1330                 JMutexAutoLock lock2(m_con_mutex);
1331
1332                 for(core::map<u16, RemoteClient*>::Iterator
1333                                 i = m_clients.getIterator();
1334                                 i.atEnd() == false; i++)
1335                 {
1336                         RemoteClient *client = i.getNode()->getValue();
1337                         
1338                         if(modified_blocks.size() > 0)
1339                         {
1340                                 // Remove block from sent history
1341                                 client->SetBlocksNotSent(modified_blocks);
1342                         }
1343                 }
1344         }
1345
1346         // Periodically print some info
1347         {
1348                 float &counter = m_print_info_timer;
1349                 counter += dtime;
1350                 if(counter >= 30.0)
1351                 {
1352                         counter = 0.0;
1353
1354                         JMutexAutoLock lock2(m_con_mutex);
1355                         
1356                         if(m_clients.size() != 0)
1357                                 infostream<<"Players:"<<std::endl;
1358                         for(core::map<u16, RemoteClient*>::Iterator
1359                                 i = m_clients.getIterator();
1360                                 i.atEnd() == false; i++)
1361                         {
1362                                 //u16 peer_id = i.getNode()->getKey();
1363                                 RemoteClient *client = i.getNode()->getValue();
1364                                 Player *player = m_env->getPlayer(client->peer_id);
1365                                 if(player==NULL)
1366                                         continue;
1367                                 infostream<<"* "<<player->getName()<<"\t";
1368                                 client->PrintInfo(infostream);
1369                         }
1370                 }
1371         }
1372
1373         //if(g_settings->getBool("enable_experimental"))
1374         {
1375
1376         /*
1377                 Check added and deleted active objects
1378         */
1379         {
1380                 //infostream<<"Server: Checking added and deleted active objects"<<std::endl;
1381                 JMutexAutoLock envlock(m_env_mutex);
1382                 JMutexAutoLock conlock(m_con_mutex);
1383
1384                 ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
1385
1386                 // Radius inside which objects are active
1387                 s16 radius = g_settings->getS16("active_object_send_range_blocks");
1388                 radius *= MAP_BLOCKSIZE;
1389
1390                 for(core::map<u16, RemoteClient*>::Iterator
1391                         i = m_clients.getIterator();
1392                         i.atEnd() == false; i++)
1393                 {
1394                         RemoteClient *client = i.getNode()->getValue();
1395
1396                         // If definitions and textures have not been sent, don't
1397                         // send objects either
1398                         if(!client->definitions_sent)
1399                                 continue;
1400
1401                         Player *player = m_env->getPlayer(client->peer_id);
1402                         if(player==NULL)
1403                         {
1404                                 // This can happen if the client timeouts somehow
1405                                 /*infostream<<"WARNING: "<<__FUNCTION_NAME<<": Client "
1406                                                 <<client->peer_id
1407                                                 <<" has no associated player"<<std::endl;*/
1408                                 continue;
1409                         }
1410                         v3s16 pos = floatToInt(player->getPosition(), BS);
1411
1412                         core::map<u16, bool> removed_objects;
1413                         core::map<u16, bool> added_objects;
1414                         m_env->getRemovedActiveObjects(pos, radius,
1415                                         client->m_known_objects, removed_objects);
1416                         m_env->getAddedActiveObjects(pos, radius,
1417                                         client->m_known_objects, added_objects);
1418                         
1419                         // Ignore if nothing happened
1420                         if(removed_objects.size() == 0 && added_objects.size() == 0)
1421                         {
1422                                 //infostream<<"active objects: none changed"<<std::endl;
1423                                 continue;
1424                         }
1425                         
1426                         std::string data_buffer;
1427
1428                         char buf[4];
1429                         
1430                         // Handle removed objects
1431                         writeU16((u8*)buf, removed_objects.size());
1432                         data_buffer.append(buf, 2);
1433                         for(core::map<u16, bool>::Iterator
1434                                         i = removed_objects.getIterator();
1435                                         i.atEnd()==false; i++)
1436                         {
1437                                 // Get object
1438                                 u16 id = i.getNode()->getKey();
1439                                 ServerActiveObject* obj = m_env->getActiveObject(id);
1440
1441                                 // Add to data buffer for sending
1442                                 writeU16((u8*)buf, i.getNode()->getKey());
1443                                 data_buffer.append(buf, 2);
1444                                 
1445                                 // Remove from known objects
1446                                 client->m_known_objects.remove(i.getNode()->getKey());
1447
1448                                 if(obj && obj->m_known_by_count > 0)
1449                                         obj->m_known_by_count--;
1450                         }
1451
1452                         // Handle added objects
1453                         writeU16((u8*)buf, added_objects.size());
1454                         data_buffer.append(buf, 2);
1455                         for(core::map<u16, bool>::Iterator
1456                                         i = added_objects.getIterator();
1457                                         i.atEnd()==false; i++)
1458                         {
1459                                 // Get object
1460                                 u16 id = i.getNode()->getKey();
1461                                 ServerActiveObject* obj = m_env->getActiveObject(id);
1462                                 
1463                                 // Get object type
1464                                 u8 type = ACTIVEOBJECT_TYPE_INVALID;
1465                                 if(obj == NULL)
1466                                         infostream<<"WARNING: "<<__FUNCTION_NAME
1467                                                         <<": NULL object"<<std::endl;
1468                                 else
1469                                         type = obj->getType();
1470
1471                                 // Add to data buffer for sending
1472                                 writeU16((u8*)buf, id);
1473                                 data_buffer.append(buf, 2);
1474                                 writeU8((u8*)buf, type);
1475                                 data_buffer.append(buf, 1);
1476                                 
1477                                 if(obj)
1478                                         data_buffer.append(serializeLongString(
1479                                                         obj->getClientInitializationData()));
1480                                 else
1481                                         data_buffer.append(serializeLongString(""));
1482
1483                                 // Add to known objects
1484                                 client->m_known_objects.insert(i.getNode()->getKey(), false);
1485
1486                                 if(obj)
1487                                         obj->m_known_by_count++;
1488                         }
1489
1490                         // Send packet
1491                         SharedBuffer<u8> reply(2 + data_buffer.size());
1492                         writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD);
1493                         memcpy((char*)&reply[2], data_buffer.c_str(),
1494                                         data_buffer.size());
1495                         // Send as reliable
1496                         m_con.Send(client->peer_id, 0, reply, true);
1497
1498                         infostream<<"Server: Sent object remove/add: "
1499                                         <<removed_objects.size()<<" removed, "
1500                                         <<added_objects.size()<<" added, "
1501                                         <<"packet size is "<<reply.getSize()<<std::endl;
1502                 }
1503
1504 #if 0
1505                 /*
1506                         Collect a list of all the objects known by the clients
1507                         and report it back to the environment.
1508                 */
1509
1510                 core::map<u16, bool> all_known_objects;
1511
1512                 for(core::map<u16, RemoteClient*>::Iterator
1513                         i = m_clients.getIterator();
1514                         i.atEnd() == false; i++)
1515                 {
1516                         RemoteClient *client = i.getNode()->getValue();
1517                         // Go through all known objects of client
1518                         for(core::map<u16, bool>::Iterator
1519                                         i = client->m_known_objects.getIterator();
1520                                         i.atEnd()==false; i++)
1521                         {
1522                                 u16 id = i.getNode()->getKey();
1523                                 all_known_objects[id] = true;
1524                         }
1525                 }
1526                 
1527                 m_env->setKnownActiveObjects(whatever);
1528 #endif
1529
1530         }
1531
1532         /*
1533                 Send object messages
1534         */
1535         {
1536                 JMutexAutoLock envlock(m_env_mutex);
1537                 JMutexAutoLock conlock(m_con_mutex);
1538
1539                 ScopeProfiler sp(g_profiler, "Server: sending object messages");
1540
1541                 // Key = object id
1542                 // Value = data sent by object
1543                 core::map<u16, core::list<ActiveObjectMessage>* > buffered_messages;
1544
1545                 // Get active object messages from environment
1546                 for(;;)
1547                 {
1548                         ActiveObjectMessage aom = m_env->getActiveObjectMessage();
1549                         if(aom.id == 0)
1550                                 break;
1551                         
1552                         core::list<ActiveObjectMessage>* message_list = NULL;
1553                         core::map<u16, core::list<ActiveObjectMessage>* >::Node *n;
1554                         n = buffered_messages.find(aom.id);
1555                         if(n == NULL)
1556                         {
1557                                 message_list = new core::list<ActiveObjectMessage>;
1558                                 buffered_messages.insert(aom.id, message_list);
1559                         }
1560                         else
1561                         {
1562                                 message_list = n->getValue();
1563                         }
1564                         message_list->push_back(aom);
1565                 }
1566                 
1567                 // Route data to every client
1568                 for(core::map<u16, RemoteClient*>::Iterator
1569                         i = m_clients.getIterator();
1570                         i.atEnd()==false; i++)
1571                 {
1572                         RemoteClient *client = i.getNode()->getValue();
1573                         std::string reliable_data;
1574                         std::string unreliable_data;
1575                         // Go through all objects in message buffer
1576                         for(core::map<u16, core::list<ActiveObjectMessage>* >::Iterator
1577                                         j = buffered_messages.getIterator();
1578                                         j.atEnd()==false; j++)
1579                         {
1580                                 // If object is not known by client, skip it
1581                                 u16 id = j.getNode()->getKey();
1582                                 if(client->m_known_objects.find(id) == NULL)
1583                                         continue;
1584                                 // Get message list of object
1585                                 core::list<ActiveObjectMessage>* list = j.getNode()->getValue();
1586                                 // Go through every message
1587                                 for(core::list<ActiveObjectMessage>::Iterator
1588                                                 k = list->begin(); k != list->end(); k++)
1589                                 {
1590                                         // Compose the full new data with header
1591                                         ActiveObjectMessage aom = *k;
1592                                         std::string new_data;
1593                                         // Add object id
1594                                         char buf[2];
1595                                         writeU16((u8*)&buf[0], aom.id);
1596                                         new_data.append(buf, 2);
1597                                         // Add data
1598                                         new_data += serializeString(aom.datastring);
1599                                         // Add data to buffer
1600                                         if(aom.reliable)
1601                                                 reliable_data += new_data;
1602                                         else
1603                                                 unreliable_data += new_data;
1604                                 }
1605                         }
1606                         /*
1607                                 reliable_data and unreliable_data are now ready.
1608                                 Send them.
1609                         */
1610                         if(reliable_data.size() > 0)
1611                         {
1612                                 SharedBuffer<u8> reply(2 + reliable_data.size());
1613                                 writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
1614                                 memcpy((char*)&reply[2], reliable_data.c_str(),
1615                                                 reliable_data.size());
1616                                 // Send as reliable
1617                                 m_con.Send(client->peer_id, 0, reply, true);
1618                         }
1619                         if(unreliable_data.size() > 0)
1620                         {
1621                                 SharedBuffer<u8> reply(2 + unreliable_data.size());
1622                                 writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
1623                                 memcpy((char*)&reply[2], unreliable_data.c_str(),
1624                                                 unreliable_data.size());
1625                                 // Send as unreliable
1626                                 m_con.Send(client->peer_id, 0, reply, false);
1627                         }
1628
1629                         /*if(reliable_data.size() > 0 || unreliable_data.size() > 0)
1630                         {
1631                                 infostream<<"Server: Size of object message data: "
1632                                                 <<"reliable: "<<reliable_data.size()
1633                                                 <<", unreliable: "<<unreliable_data.size()
1634                                                 <<std::endl;
1635                         }*/
1636                 }
1637
1638                 // Clear buffered_messages
1639                 for(core::map<u16, core::list<ActiveObjectMessage>* >::Iterator
1640                                 i = buffered_messages.getIterator();
1641                                 i.atEnd()==false; i++)
1642                 {
1643                         delete i.getNode()->getValue();
1644                 }
1645         }
1646
1647         } // enable_experimental
1648
1649         /*
1650                 Send queued-for-sending map edit events.
1651         */
1652         {
1653                 // Don't send too many at a time
1654                 //u32 count = 0;
1655
1656                 // Single change sending is disabled if queue size is not small
1657                 bool disable_single_change_sending = false;
1658                 if(m_unsent_map_edit_queue.size() >= 4)
1659                         disable_single_change_sending = true;
1660
1661                 bool got_any_events = false;
1662
1663                 // We'll log the amount of each
1664                 Profiler prof;
1665
1666                 while(m_unsent_map_edit_queue.size() != 0)
1667                 {
1668                         got_any_events = true;
1669
1670                         MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
1671                         
1672                         // Players far away from the change are stored here.
1673                         // Instead of sending the changes, MapBlocks are set not sent
1674                         // for them.
1675                         core::list<u16> far_players;
1676
1677                         if(event->type == MEET_ADDNODE)
1678                         {
1679                                 //infostream<<"Server: MEET_ADDNODE"<<std::endl;
1680                                 prof.add("MEET_ADDNODE", 1);
1681                                 if(disable_single_change_sending)
1682                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
1683                                                         &far_players, 5);
1684                                 else
1685                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
1686                                                         &far_players, 30);
1687                         }
1688                         else if(event->type == MEET_REMOVENODE)
1689                         {
1690                                 //infostream<<"Server: MEET_REMOVENODE"<<std::endl;
1691                                 prof.add("MEET_REMOVENODE", 1);
1692                                 if(disable_single_change_sending)
1693                                         sendRemoveNode(event->p, event->already_known_by_peer,
1694                                                         &far_players, 5);
1695                                 else
1696                                         sendRemoveNode(event->p, event->already_known_by_peer,
1697                                                         &far_players, 30);
1698                         }
1699                         else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
1700                         {
1701                                 infostream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
1702                                 prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
1703                                 setBlockNotSent(event->p);
1704                         }
1705                         else if(event->type == MEET_OTHER)
1706                         {
1707                                 infostream<<"Server: MEET_OTHER"<<std::endl;
1708                                 prof.add("MEET_OTHER", 1);
1709                                 for(core::map<v3s16, bool>::Iterator
1710                                                 i = event->modified_blocks.getIterator();
1711                                                 i.atEnd()==false; i++)
1712                                 {
1713                                         v3s16 p = i.getNode()->getKey();
1714                                         setBlockNotSent(p);
1715                                 }
1716                         }
1717                         else
1718                         {
1719                                 prof.add("unknown", 1);
1720                                 infostream<<"WARNING: Server: Unknown MapEditEvent "
1721                                                 <<((u32)event->type)<<std::endl;
1722                         }
1723                         
1724                         /*
1725                                 Set blocks not sent to far players
1726                         */
1727                         if(far_players.size() > 0)
1728                         {
1729                                 // Convert list format to that wanted by SetBlocksNotSent
1730                                 core::map<v3s16, MapBlock*> modified_blocks2;
1731                                 for(core::map<v3s16, bool>::Iterator
1732                                                 i = event->modified_blocks.getIterator();
1733                                                 i.atEnd()==false; i++)
1734                                 {
1735                                         v3s16 p = i.getNode()->getKey();
1736                                         modified_blocks2.insert(p,
1737                                                         m_env->getMap().getBlockNoCreateNoEx(p));
1738                                 }
1739                                 // Set blocks not sent
1740                                 for(core::list<u16>::Iterator
1741                                                 i = far_players.begin();
1742                                                 i != far_players.end(); i++)
1743                                 {
1744                                         u16 peer_id = *i;
1745                                         RemoteClient *client = getClient(peer_id);
1746                                         if(client==NULL)
1747                                                 continue;
1748                                         client->SetBlocksNotSent(modified_blocks2);
1749                                 }
1750                         }
1751
1752                         delete event;
1753
1754                         /*// Don't send too many at a time
1755                         count++;
1756                         if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
1757                                 break;*/
1758                 }
1759
1760                 if(got_any_events)
1761                 {
1762                         infostream<<"Server: MapEditEvents:"<<std::endl;
1763                         prof.print(infostream);
1764                 }
1765                 
1766         }
1767
1768         /*
1769                 Trigger emergethread (it somehow gets to a non-triggered but
1770                 bysy state sometimes)
1771         */
1772         {
1773                 float &counter = m_emergethread_trigger_timer;
1774                 counter += dtime;
1775                 if(counter >= 2.0)
1776                 {
1777                         counter = 0.0;
1778                         
1779                         m_emergethread.trigger();
1780                 }
1781         }
1782
1783         // Save map, players and auth stuff
1784         {
1785                 float &counter = m_savemap_timer;
1786                 counter += dtime;
1787                 if(counter >= g_settings->getFloat("server_map_save_interval"))
1788                 {
1789                         counter = 0.0;
1790
1791                         ScopeProfiler sp(g_profiler, "Server: saving stuff");
1792
1793                         // Auth stuff
1794                         if(m_authmanager.isModified())
1795                                 m_authmanager.save();
1796
1797                         //Bann stuff
1798                         if(m_banmanager.isModified())
1799                                 m_banmanager.save();
1800                         
1801                         // Map
1802                         JMutexAutoLock lock(m_env_mutex);
1803
1804                         // Save changed parts of map
1805                         m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
1806
1807                         // Save players
1808                         m_env->serializePlayers(m_mapsavedir);
1809                         
1810                         // Save environment metadata
1811                         m_env->saveMeta(m_mapsavedir);
1812                 }
1813         }
1814 }
1815
1816 void Server::Receive()
1817 {
1818         DSTACK(__FUNCTION_NAME);
1819         SharedBuffer<u8> data;
1820         u16 peer_id;
1821         u32 datasize;
1822         try{
1823                 {
1824                         JMutexAutoLock conlock(m_con_mutex);
1825                         datasize = m_con.Receive(peer_id, data);
1826                 }
1827
1828                 // This has to be called so that the client list gets synced
1829                 // with the peer list of the connection
1830                 handlePeerChanges();
1831
1832                 ProcessData(*data, datasize, peer_id);
1833         }
1834         catch(con::InvalidIncomingDataException &e)
1835         {
1836                 infostream<<"Server::Receive(): "
1837                                 "InvalidIncomingDataException: what()="
1838                                 <<e.what()<<std::endl;
1839         }
1840         catch(con::PeerNotFoundException &e)
1841         {
1842                 //NOTE: This is not needed anymore
1843                 
1844                 // The peer has been disconnected.
1845                 // Find the associated player and remove it.
1846
1847                 /*JMutexAutoLock envlock(m_env_mutex);
1848
1849                 infostream<<"ServerThread: peer_id="<<peer_id
1850                                 <<" has apparently closed connection. "
1851                                 <<"Removing player."<<std::endl;
1852
1853                 m_env->removePlayer(peer_id);*/
1854         }
1855 }
1856
1857 void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
1858 {
1859         DSTACK(__FUNCTION_NAME);
1860         // Environment is locked first.
1861         JMutexAutoLock envlock(m_env_mutex);
1862         JMutexAutoLock conlock(m_con_mutex);
1863         
1864         try{
1865                 Address address = m_con.GetPeerAddress(peer_id);
1866
1867                 // drop player if is ip is banned
1868                 if(m_banmanager.isIpBanned(address.serializeString())){
1869                         SendAccessDenied(m_con, peer_id,
1870                                         L"Your ip is banned. Banned name was "
1871                                         +narrow_to_wide(m_banmanager.getBanName(
1872                                                 address.serializeString())));
1873                         m_con.DeletePeer(peer_id);
1874                         return;
1875                 }
1876         }
1877         catch(con::PeerNotFoundException &e)
1878         {
1879                 infostream<<"Server::ProcessData(): Cancelling: peer "
1880                                 <<peer_id<<" not found"<<std::endl;
1881                 return;
1882         }
1883
1884         u8 peer_ser_ver = getClient(peer_id)->serialization_version;
1885
1886         try
1887         {
1888
1889         if(datasize < 2)
1890                 return;
1891
1892         ToServerCommand command = (ToServerCommand)readU16(&data[0]);
1893         
1894         if(command == TOSERVER_INIT)
1895         {
1896                 // [0] u16 TOSERVER_INIT
1897                 // [2] u8 SER_FMT_VER_HIGHEST
1898                 // [3] u8[20] player_name
1899                 // [23] u8[28] password <--- can be sent without this, from old versions
1900
1901                 if(datasize < 2+1+PLAYERNAME_SIZE)
1902                         return;
1903
1904                 infostream<<"Server: Got TOSERVER_INIT from "
1905                                 <<peer_id<<std::endl;
1906
1907                 // First byte after command is maximum supported
1908                 // serialization version
1909                 u8 client_max = data[2];
1910                 u8 our_max = SER_FMT_VER_HIGHEST;
1911                 // Use the highest version supported by both
1912                 u8 deployed = core::min_(client_max, our_max);
1913                 // If it's lower than the lowest supported, give up.
1914                 if(deployed < SER_FMT_VER_LOWEST)
1915                         deployed = SER_FMT_VER_INVALID;
1916
1917                 //peer->serialization_version = deployed;
1918                 getClient(peer_id)->pending_serialization_version = deployed;
1919                 
1920                 if(deployed == SER_FMT_VER_INVALID)
1921                 {
1922                         infostream<<"Server: Cannot negotiate "
1923                                         "serialization version with peer "
1924                                         <<peer_id<<std::endl;
1925                         SendAccessDenied(m_con, peer_id, std::wstring(
1926                                         L"Your client's version is not supported.\n"
1927                                         L"Server version is ")
1928                                         + narrow_to_wide(VERSION_STRING) + L"."
1929                         );
1930                         return;
1931                 }
1932                 
1933                 /*
1934                         Read and check network protocol version
1935                 */
1936
1937                 u16 net_proto_version = 0;
1938                 if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2)
1939                 {
1940                         net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
1941                 }
1942
1943                 getClient(peer_id)->net_proto_version = net_proto_version;
1944
1945                 if(net_proto_version == 0)
1946                 {
1947                         SendAccessDenied(m_con, peer_id, std::wstring(
1948                                         L"Your client's version is not supported.\n"
1949                                         L"Server version is ")
1950                                         + narrow_to_wide(VERSION_STRING) + L"."
1951                         );
1952                         return;
1953                 }
1954                 
1955                 if(g_settings->getBool("strict_protocol_version_checking"))
1956                 {
1957                         if(net_proto_version != PROTOCOL_VERSION)
1958                         {
1959                                 SendAccessDenied(m_con, peer_id, std::wstring(
1960                                                 L"Your client's version is not supported.\n"
1961                                                 L"Server version is ")
1962                                                 + narrow_to_wide(VERSION_STRING) + L",\n"
1963                                                 + L"server's PROTOCOL_VERSION is "
1964                                                 + narrow_to_wide(itos(PROTOCOL_VERSION))
1965                                                 + L", client's PROTOCOL_VERSION is "
1966                                                 + narrow_to_wide(itos(net_proto_version))
1967                                 );
1968                                 return;
1969                         }
1970                 }
1971
1972                 /*
1973                         Set up player
1974                 */
1975                 
1976                 // Get player name
1977                 char playername[PLAYERNAME_SIZE];
1978                 for(u32 i=0; i<PLAYERNAME_SIZE-1; i++)
1979                 {
1980                         playername[i] = data[3+i];
1981                 }
1982                 playername[PLAYERNAME_SIZE-1] = 0;
1983                 
1984                 if(playername[0]=='\0')
1985                 {
1986                         infostream<<"Server: Player has empty name"<<std::endl;
1987                         SendAccessDenied(m_con, peer_id,
1988                                         L"Empty name");
1989                         return;
1990                 }
1991
1992                 if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false)
1993                 {
1994                         infostream<<"Server: Player has invalid name"<<std::endl;
1995                         SendAccessDenied(m_con, peer_id,
1996                                         L"Name contains unallowed characters");
1997                         return;
1998                 }
1999
2000                 // Get password
2001                 char password[PASSWORD_SIZE];
2002                 if(datasize < 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE)
2003                 {
2004                         // old version - assume blank password
2005                         password[0] = 0;
2006                 }
2007                 else
2008                 {
2009                                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2010                                 {
2011                                         password[i] = data[23+i];
2012                                 }
2013                                 password[PASSWORD_SIZE-1] = 0;
2014                 }
2015                 
2016                 // Add player to auth manager
2017                 if(m_authmanager.exists(playername) == false)
2018                 {
2019                         std::wstring default_password =
2020                                 narrow_to_wide(g_settings->get("default_password"));
2021                         std::string translated_default_password =
2022                                 translatePassword(playername, default_password);
2023
2024                         // If default_password is empty, allow any initial password
2025                         if (default_password.length() == 0)
2026                                 translated_default_password = password;
2027
2028                         infostream<<"Server: adding player "<<playername
2029                                         <<" to auth manager"<<std::endl;
2030                         m_authmanager.add(playername);
2031                         m_authmanager.setPassword(playername, translated_default_password);
2032                         m_authmanager.setPrivs(playername,
2033                                         stringToPrivs(g_settings->get("default_privs")));
2034                         m_authmanager.save();
2035                 }
2036
2037                 std::string checkpwd = m_authmanager.getPassword(playername);
2038
2039                 /*infostream<<"Server: Client gave password '"<<password
2040                                 <<"', the correct one is '"<<checkpwd<<"'"<<std::endl;*/
2041
2042                 if(password != checkpwd)
2043                 {
2044                         infostream<<"Server: peer_id="<<peer_id
2045                                         <<": supplied invalid password for "
2046                                         <<playername<<std::endl;
2047                         SendAccessDenied(m_con, peer_id, L"Invalid password");
2048                         return;
2049                 }
2050                 
2051                 // Enforce user limit.
2052                 // Don't enforce for users that have some admin right
2053                 if(m_clients.size() >= g_settings->getU16("max_users") &&
2054                                 (m_authmanager.getPrivs(playername)
2055                                         & (PRIV_SERVER|PRIV_BAN|PRIV_PRIVS|PRIV_PASSWORD)) == 0 &&
2056                                 playername != g_settings->get("name"))
2057                 {
2058                         SendAccessDenied(m_con, peer_id, L"Too many users.");
2059                         return;
2060                 }
2061
2062                 // Get player
2063                 ServerRemotePlayer *player = emergePlayer(playername, peer_id);
2064
2065                 // If failed, cancel
2066                 if(player == NULL)
2067                 {
2068                         infostream<<"Server: peer_id="<<peer_id
2069                                         <<": failed to emerge player"<<std::endl;
2070                         return;
2071                 }
2072
2073                 /*
2074                         Answer with a TOCLIENT_INIT
2075                 */
2076                 {
2077                         SharedBuffer<u8> reply(2+1+6+8);
2078                         writeU16(&reply[0], TOCLIENT_INIT);
2079                         writeU8(&reply[2], deployed);
2080                         writeV3S16(&reply[2+1], floatToInt(player->getPosition()+v3f(0,BS/2,0), BS));
2081                         writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
2082                         
2083                         // Send as reliable
2084                         m_con.Send(peer_id, 0, reply, true);
2085                 }
2086
2087                 /*
2088                         Send complete position information
2089                 */
2090                 SendMovePlayer(player);
2091
2092                 return;
2093         }
2094
2095         if(command == TOSERVER_INIT2)
2096         {
2097                 infostream<<"Server: Got TOSERVER_INIT2 from "
2098                                 <<peer_id<<std::endl;
2099
2100
2101                 getClient(peer_id)->serialization_version
2102                                 = getClient(peer_id)->pending_serialization_version;
2103
2104                 /*
2105                         Send some initialization data
2106                 */
2107
2108                 // Send item definitions
2109                 SendItemDef(m_con, peer_id, m_itemdef);
2110                 
2111                 // Send node definitions
2112                 SendNodeDef(m_con, peer_id, m_nodedef);
2113                 
2114                 // Send texture announcement
2115                 SendTextureAnnouncement(peer_id);
2116                 
2117                 // Send player info to all players
2118                 //SendPlayerInfos();
2119
2120                 // Send inventory to player
2121                 UpdateCrafting(peer_id);
2122                 SendInventory(peer_id);
2123                 
2124                 // Send player items to all players
2125                 SendPlayerItems();
2126
2127                 Player *player = m_env->getPlayer(peer_id);
2128
2129                 // Send HP
2130                 SendPlayerHP(player);
2131                 
2132                 // Send time of day
2133                 {
2134                         SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
2135                                         m_env->getTimeOfDay());
2136                         m_con.Send(peer_id, 0, data, true);
2137                 }
2138                 
2139                 // Send information about server to player in chat
2140                 SendChatMessage(peer_id, getStatusString());
2141                 
2142                 // Send information about joining in chat
2143                 {
2144                         std::wstring name = L"unknown";
2145                         Player *player = m_env->getPlayer(peer_id);
2146                         if(player != NULL)
2147                                 name = narrow_to_wide(player->getName());
2148                         
2149                         std::wstring message;
2150                         message += L"*** ";
2151                         message += name;
2152                         message += L" joined game";
2153                         BroadcastChatMessage(message);
2154                 }
2155                 
2156                 // Warnings about protocol version can be issued here
2157                 if(getClient(peer_id)->net_proto_version < PROTOCOL_VERSION)
2158                 {
2159                         SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER");
2160                 }
2161
2162                 /*
2163                         Check HP, respawn if necessary
2164                 */
2165                 HandlePlayerHP(player, 0);
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                 if(g_settings->getBool("enable_damage"))
2666                 {
2667                         actionstream<<player->getName()<<" damaged by "
2668                                         <<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
2669                                         <<std::endl;
2670                                 
2671                         HandlePlayerHP(player, damage);
2672                 }
2673                 else
2674                 {
2675                         SendPlayerHP(player);
2676                 }
2677         }
2678         else if(command == TOSERVER_PASSWORD)
2679         {
2680                 /*
2681                         [0] u16 TOSERVER_PASSWORD
2682                         [2] u8[28] old password
2683                         [30] u8[28] new password
2684                 */
2685
2686                 if(datasize != 2+PASSWORD_SIZE*2)
2687                         return;
2688                 /*char password[PASSWORD_SIZE];
2689                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2690                         password[i] = data[2+i];
2691                 password[PASSWORD_SIZE-1] = 0;*/
2692                 std::string oldpwd;
2693                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2694                 {
2695                         char c = data[2+i];
2696                         if(c == 0)
2697                                 break;
2698                         oldpwd += c;
2699                 }
2700                 std::string newpwd;
2701                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2702                 {
2703                         char c = data[2+PASSWORD_SIZE+i];
2704                         if(c == 0)
2705                                 break;
2706                         newpwd += c;
2707                 }
2708
2709                 infostream<<"Server: Client requests a password change from "
2710                                 <<"'"<<oldpwd<<"' to '"<<newpwd<<"'"<<std::endl;
2711
2712                 std::string playername = player->getName();
2713
2714                 if(m_authmanager.exists(playername) == false)
2715                 {
2716                         infostream<<"Server: playername not found in authmanager"<<std::endl;
2717                         // Wrong old password supplied!!
2718                         SendChatMessage(peer_id, L"playername not found in authmanager");
2719                         return;
2720                 }
2721
2722                 std::string checkpwd = m_authmanager.getPassword(playername);
2723
2724                 if(oldpwd != checkpwd)
2725                 {
2726                         infostream<<"Server: invalid old password"<<std::endl;
2727                         // Wrong old password supplied!!
2728                         SendChatMessage(peer_id, L"Invalid old password supplied. Password NOT changed.");
2729                         return;
2730                 }
2731
2732                 actionstream<<player->getName()<<" changes password"<<std::endl;
2733
2734                 m_authmanager.setPassword(playername, newpwd);
2735                 
2736                 infostream<<"Server: password change successful for "<<playername
2737                                 <<std::endl;
2738                 SendChatMessage(peer_id, L"Password change successful");
2739         }
2740         else if(command == TOSERVER_PLAYERITEM)
2741         {
2742                 if (datasize < 2+2)
2743                         return;
2744
2745                 u16 item = readU16(&data[2]);
2746                 srp->setWieldIndex(item);
2747                 SendWieldedItem(srp);
2748         }
2749         else if(command == TOSERVER_RESPAWN)
2750         {
2751                 if(player->hp != 0)
2752                         return;
2753                 
2754                 srp->m_respawn_active = false;
2755
2756                 RespawnPlayer(player);
2757                 
2758                 actionstream<<player->getName()<<" respawns at "
2759                                 <<PP(player->getPosition()/BS)<<std::endl;
2760
2761                 // ActiveObject is added to environment in AsyncRunStep after
2762                 // the previous addition has been succesfully removed
2763         }
2764         else if(command == TOSERVER_REQUEST_TEXTURES) {
2765                 std::string datastring((char*)&data[2], datasize-2);
2766                 std::istringstream is(datastring, std::ios_base::binary);
2767
2768                 infostream<<"TOSERVER_REQUEST_TEXTURES: "<<std::endl;
2769
2770                 core::list<TextureRequest> tosend;
2771
2772                 u16 numtextures = readU16(is);
2773
2774                 for(int i = 0; i < numtextures; i++) {
2775
2776                         std::string name = deSerializeString(is);
2777
2778                         tosend.push_back(TextureRequest(name));
2779                         infostream<<"TOSERVER_REQUEST_TEXTURES: requested texture " << name <<std::endl;
2780                 }
2781
2782                 SendTexturesRequested(peer_id, tosend);
2783
2784                 // Now the client should know about everything
2785                 // (definitions and textures)
2786                 getClient(peer_id)->definitions_sent = true;
2787         }
2788         else if(command == TOSERVER_INTERACT)
2789         {
2790                 std::string datastring((char*)&data[2], datasize-2);
2791                 std::istringstream is(datastring, std::ios_base::binary);
2792
2793                 /*
2794                         [0] u16 command
2795                         [2] u8 action
2796                         [3] u16 item
2797                         [5] u32 length of the next item
2798                         [9] serialized PointedThing
2799                         actions:
2800                         0: start digging (from undersurface) or use
2801                         1: stop digging (all parameters ignored)
2802                         2: digging completed
2803                         3: place block or item (to abovesurface)
2804                         4: use item
2805                 */
2806                 u8 action = readU8(is);
2807                 u16 item_i = readU16(is);
2808                 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
2809                 PointedThing pointed;
2810                 pointed.deSerialize(tmp_is);
2811
2812                 infostream<<"TOSERVER_INTERACT: action="<<(int)action<<", item="<<item_i<<", pointed="<<pointed.dump()<<std::endl;
2813
2814                 v3f player_pos = srp->m_last_good_position;
2815
2816                 // Update wielded item
2817                 if(srp->getWieldIndex() != item_i)
2818                 {
2819                         srp->setWieldIndex(item_i);
2820                         SendWieldedItem(srp);
2821                 }
2822
2823                 // Get pointed to node (undefined if not POINTEDTYPE_NODE)
2824                 v3s16 p_under = pointed.node_undersurface;
2825                 v3s16 p_above = pointed.node_abovesurface;
2826
2827                 // Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
2828                 ServerActiveObject *pointed_object = NULL;
2829                 if(pointed.type == POINTEDTHING_OBJECT)
2830                 {
2831                         pointed_object = m_env->getActiveObject(pointed.object_id);
2832                         if(pointed_object == NULL)
2833                         {
2834                                 infostream<<"TOSERVER_INTERACT: "
2835                                         "pointed object is NULL"<<std::endl;
2836                                 return;
2837                         }
2838
2839                 }
2840
2841                 v3f pointed_pos_under = player_pos;
2842                 v3f pointed_pos_above = player_pos;
2843                 if(pointed.type == POINTEDTHING_NODE)
2844                 {
2845                         pointed_pos_under = intToFloat(p_under, BS);
2846                         pointed_pos_above = intToFloat(p_above, BS);
2847                 }
2848                 else if(pointed.type == POINTEDTHING_OBJECT)
2849                 {
2850                         pointed_pos_under = pointed_object->getBasePosition();
2851                         pointed_pos_above = pointed_pos_under;
2852                 }
2853
2854                 /*
2855                         Check that target is reasonably close
2856                         (only when digging or placing things)
2857                 */
2858                 if(action == 0 || action == 2 || action == 3)
2859                 {
2860                         float d = player_pos.getDistanceFrom(pointed_pos_under);
2861                         float max_d = BS * 10; // Just some large enough value
2862                         if(d > max_d){
2863                                 actionstream<<"Player "<<player->getName()
2864                                                 <<" tried to access "<<pointed.dump()
2865                                                 <<" from too far: "
2866                                                 <<"d="<<d<<", max_d="<<max_d
2867                                                 <<". ignoring."<<std::endl;
2868                                 // Re-send block to revert change on client-side
2869                                 RemoteClient *client = getClient(peer_id);
2870                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2871                                 client->SetBlockNotSent(blockpos);
2872                                 // Do nothing else
2873                                 return;
2874                         }
2875                 }
2876
2877                 /*
2878                         Make sure the player is allowed to do it
2879                 */
2880                 if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
2881                 {
2882                         infostream<<"Ignoring interaction from player "<<player->getName()
2883                                         <<" because privileges are "<<getPlayerPrivs(player)
2884                                         <<std::endl;
2885                         return;
2886                 }
2887
2888                 /*
2889                         0: start digging or punch object
2890                 */
2891                 if(action == 0)
2892                 {
2893                         if(pointed.type == POINTEDTHING_NODE)
2894                         {
2895                                 /*
2896                                         NOTE: This can be used in the future to check if
2897                                         somebody is cheating, by checking the timing.
2898                                 */
2899                                 MapNode n(CONTENT_IGNORE);
2900                                 try
2901                                 {
2902                                         n = m_env->getMap().getNode(p_under);
2903                                 }
2904                                 catch(InvalidPositionException &e)
2905                                 {
2906                                         infostream<<"Server: Not punching: Node not found."
2907                                                         <<" Adding block to emerge queue."
2908                                                         <<std::endl;
2909                                         m_emerge_queue.addBlock(peer_id,
2910                                                         getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
2911                                 }
2912                                 if(n.getContent() != CONTENT_IGNORE)
2913                                         scriptapi_node_on_punch(m_lua, p_under, n, srp);
2914                         }
2915                         else if(pointed.type == POINTEDTHING_OBJECT)
2916                         {
2917                                 // Skip if object has been removed
2918                                 if(pointed_object->m_removed)
2919                                         return;
2920
2921                                 actionstream<<player->getName()<<" punches object "
2922                                         <<pointed.object_id<<std::endl;
2923
2924                                 // Do stuff
2925                                 pointed_object->punch(srp, srp->m_time_from_last_punch);
2926                                 srp->m_time_from_last_punch = 0;
2927                         }
2928
2929                 } // action == 0
2930
2931                 /*
2932                         1: stop digging
2933                 */
2934                 else if(action == 1)
2935                 {
2936                 } // action == 1
2937
2938                 /*
2939                         2: Digging completed
2940                 */
2941                 else if(action == 2)
2942                 {
2943                         // Only complete digging of nodes
2944                         if(pointed.type == POINTEDTHING_NODE)
2945                         {
2946                                 MapNode n(CONTENT_IGNORE);
2947                                 try
2948                                 {
2949                                         n = m_env->getMap().getNode(p_under);
2950                                 }
2951                                 catch(InvalidPositionException &e)
2952                                 {
2953                                         infostream<<"Server: Not finishing digging: Node not found."
2954                                                         <<" Adding block to emerge queue."
2955                                                         <<std::endl;
2956                                         m_emerge_queue.addBlock(peer_id,
2957                                                         getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
2958                                 }
2959                                 if(n.getContent() != CONTENT_IGNORE)
2960                                         scriptapi_node_on_dig(m_lua, p_under, n, srp);
2961                         }
2962                 } // action == 2
2963                 
2964                 /*
2965                         3: place block or right-click object
2966                 */
2967                 else if(action == 3)
2968                 {
2969                         ItemStack item = srp->getWieldedItem();
2970
2971                         // Reset build time counter
2972                         if(pointed.type == POINTEDTHING_NODE &&
2973                                         item.getDefinition(m_itemdef).type == ITEM_NODE)
2974                                 getClient(peer_id)->m_time_from_building = 0.0;
2975
2976                         if(pointed.type == POINTEDTHING_OBJECT)
2977                         {
2978                                 // Right click object
2979
2980                                 // Skip if object has been removed
2981                                 if(pointed_object->m_removed)
2982                                         return;
2983
2984                                 actionstream<<player->getName()<<" right-clicks object "
2985                                         <<pointed.object_id<<std::endl;
2986
2987                                 // Do stuff
2988                                 pointed_object->rightClick(srp);
2989                         }
2990                         else if(scriptapi_item_on_place(m_lua,
2991                                         item, srp, pointed))
2992                         {
2993                                 // Placement was handled in lua
2994
2995                                 // Apply returned ItemStack
2996                                 if(g_settings->getBool("creative_mode") == false)
2997                                         srp->setWieldedItem(item);
2998                         }
2999
3000                 } // action == 3
3001
3002                 /*
3003                         4: use
3004                 */
3005                 else if(action == 4)
3006                 {
3007                         ItemStack item = srp->getWieldedItem();
3008
3009                         actionstream<<player->getName()<<" uses "<<item.name
3010                                         <<", pointing at "<<pointed.dump()<<std::endl;
3011
3012                         if(scriptapi_item_on_use(m_lua,
3013                                         item, srp, pointed))
3014                         {
3015                                 // Apply returned ItemStack
3016                                 if(g_settings->getBool("creative_mode") == false)
3017                                         srp->setWieldedItem(item);
3018                         }
3019
3020                 } // action == 4
3021
3022                 /*
3023                         Catch invalid actions
3024                 */
3025                 else
3026                 {
3027                         infostream<<"WARNING: Server: Invalid action "
3028                                         <<action<<std::endl;
3029                 }
3030         }
3031         else
3032         {
3033                 infostream<<"Server::ProcessData(): Ignoring "
3034                                 "unknown command "<<command<<std::endl;
3035         }
3036         
3037         } //try
3038         catch(SendFailedException &e)
3039         {
3040                 errorstream<<"Server::ProcessData(): SendFailedException: "
3041                                 <<"what="<<e.what()
3042                                 <<std::endl;
3043         }
3044 }
3045
3046 void Server::onMapEditEvent(MapEditEvent *event)
3047 {
3048         //infostream<<"Server::onMapEditEvent()"<<std::endl;
3049         if(m_ignore_map_edit_events)
3050                 return;
3051         MapEditEvent *e = event->clone();
3052         m_unsent_map_edit_queue.push_back(e);
3053 }
3054
3055 Inventory* Server::getInventory(const InventoryLocation &loc)
3056 {
3057         switch(loc.type){
3058         case InventoryLocation::UNDEFINED:
3059         {}
3060         break;
3061         case InventoryLocation::CURRENT_PLAYER:
3062         {}
3063         break;
3064         case InventoryLocation::PLAYER:
3065         {
3066                 Player *player = m_env->getPlayer(loc.name.c_str());
3067                 if(!player)
3068                         return NULL;
3069                 return &player->inventory;
3070         }
3071         break;
3072         case InventoryLocation::NODEMETA:
3073         {
3074                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3075                 if(!meta)
3076                         return NULL;
3077                 return meta->getInventory();
3078         }
3079         break;
3080         default:
3081                 assert(0);
3082         }
3083         return NULL;
3084 }
3085 std::string Server::getInventoryOwner(const InventoryLocation &loc)
3086 {
3087         switch(loc.type){
3088         case InventoryLocation::UNDEFINED:
3089         {}
3090         break;
3091         case InventoryLocation::CURRENT_PLAYER:
3092         {}
3093         break;
3094         case InventoryLocation::PLAYER:
3095         {
3096                 return loc.name;
3097         }
3098         break;
3099         case InventoryLocation::NODEMETA:
3100         {
3101                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3102                 if(!meta)
3103                         return "";
3104                 return meta->getOwner();
3105         }
3106         break;
3107         default:
3108                 assert(0);
3109         }
3110         return "";
3111 }
3112 void Server::setInventoryModified(const InventoryLocation &loc)
3113 {
3114         switch(loc.type){
3115         case InventoryLocation::UNDEFINED:
3116         {}
3117         break;
3118         case InventoryLocation::PLAYER:
3119         {
3120                 ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>
3121                                 (m_env->getPlayer(loc.name.c_str()));
3122                 if(!srp)
3123                         return;
3124                 srp->m_inventory_not_sent = true;
3125         }
3126         break;
3127         case InventoryLocation::NODEMETA:
3128         {
3129                 v3s16 blockpos = getNodeBlockPos(loc.p);
3130
3131                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3132                 if(meta)
3133                         meta->inventoryModified();
3134                 
3135                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
3136                 if(block)
3137                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
3138                 
3139                 setBlockNotSent(blockpos);
3140         }
3141         break;
3142         default:
3143                 assert(0);
3144         }
3145 }
3146
3147 core::list<PlayerInfo> Server::getPlayerInfo()
3148 {
3149         DSTACK(__FUNCTION_NAME);
3150         JMutexAutoLock envlock(m_env_mutex);
3151         JMutexAutoLock conlock(m_con_mutex);
3152         
3153         core::list<PlayerInfo> list;
3154
3155         core::list<Player*> players = m_env->getPlayers();
3156         
3157         core::list<Player*>::Iterator i;
3158         for(i = players.begin();
3159                         i != players.end(); i++)
3160         {
3161                 PlayerInfo info;
3162
3163                 Player *player = *i;
3164
3165                 try{
3166                         // Copy info from connection to info struct
3167                         info.id = player->peer_id;
3168                         info.address = m_con.GetPeerAddress(player->peer_id);
3169                         info.avg_rtt = m_con.GetPeerAvgRTT(player->peer_id);
3170                 }
3171                 catch(con::PeerNotFoundException &e)
3172                 {
3173                         // Set dummy peer info
3174                         info.id = 0;
3175                         info.address = Address(0,0,0,0,0);
3176                         info.avg_rtt = 0.0;
3177                 }
3178
3179                 snprintf(info.name, PLAYERNAME_SIZE, "%s", player->getName());
3180                 info.position = player->getPosition();
3181
3182                 list.push_back(info);
3183         }
3184
3185         return list;
3186 }
3187
3188
3189 void Server::peerAdded(con::Peer *peer)
3190 {
3191         DSTACK(__FUNCTION_NAME);
3192         infostream<<"Server::peerAdded(): peer->id="
3193                         <<peer->id<<std::endl;
3194         
3195         PeerChange c;
3196         c.type = PEER_ADDED;
3197         c.peer_id = peer->id;
3198         c.timeout = false;
3199         m_peer_change_queue.push_back(c);
3200 }
3201
3202 void Server::deletingPeer(con::Peer *peer, bool timeout)
3203 {
3204         DSTACK(__FUNCTION_NAME);
3205         infostream<<"Server::deletingPeer(): peer->id="
3206                         <<peer->id<<", timeout="<<timeout<<std::endl;
3207         
3208         PeerChange c;
3209         c.type = PEER_REMOVED;
3210         c.peer_id = peer->id;
3211         c.timeout = timeout;
3212         m_peer_change_queue.push_back(c);
3213 }
3214
3215 /*
3216         Static send methods
3217 */
3218
3219 void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp)
3220 {
3221         DSTACK(__FUNCTION_NAME);
3222         std::ostringstream os(std::ios_base::binary);
3223
3224         writeU16(os, TOCLIENT_HP);
3225         writeU8(os, hp);
3226
3227         // Make data buffer
3228         std::string s = os.str();
3229         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3230         // Send as reliable
3231         con.Send(peer_id, 0, data, true);
3232 }
3233
3234 void Server::SendAccessDenied(con::Connection &con, u16 peer_id,
3235                 const std::wstring &reason)
3236 {
3237         DSTACK(__FUNCTION_NAME);
3238         std::ostringstream os(std::ios_base::binary);
3239
3240         writeU16(os, TOCLIENT_ACCESS_DENIED);
3241         os<<serializeWideString(reason);
3242
3243         // Make data buffer
3244         std::string s = os.str();
3245         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3246         // Send as reliable
3247         con.Send(peer_id, 0, data, true);
3248 }
3249
3250 void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
3251                 bool set_camera_point_target, v3f camera_point_target)
3252 {
3253         DSTACK(__FUNCTION_NAME);
3254         std::ostringstream os(std::ios_base::binary);
3255
3256         writeU16(os, TOCLIENT_DEATHSCREEN);
3257         writeU8(os, set_camera_point_target);
3258         writeV3F1000(os, camera_point_target);
3259
3260         // Make data buffer
3261         std::string s = os.str();
3262         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3263         // Send as reliable
3264         con.Send(peer_id, 0, data, true);
3265 }
3266
3267 void Server::SendItemDef(con::Connection &con, u16 peer_id,
3268                 IItemDefManager *itemdef)
3269 {
3270         DSTACK(__FUNCTION_NAME);
3271         std::ostringstream os(std::ios_base::binary);
3272
3273         /*
3274                 u16 command
3275                 u32 length of the next item
3276                 zlib-compressed serialized ItemDefManager
3277         */
3278         writeU16(os, TOCLIENT_ITEMDEF);
3279         std::ostringstream tmp_os(std::ios::binary);
3280         itemdef->serialize(tmp_os);
3281         std::ostringstream tmp_os2(std::ios::binary);
3282         compressZlib(tmp_os.str(), tmp_os2);
3283         os<<serializeLongString(tmp_os2.str());
3284
3285         // Make data buffer
3286         std::string s = os.str();
3287         infostream<<"Server::SendItemDef(): Sending item definitions: size="
3288                         <<s.size()<<std::endl;
3289         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3290         // Send as reliable
3291         con.Send(peer_id, 0, data, true);
3292 }
3293
3294 void Server::SendNodeDef(con::Connection &con, u16 peer_id,
3295                 INodeDefManager *nodedef)
3296 {
3297         DSTACK(__FUNCTION_NAME);
3298         std::ostringstream os(std::ios_base::binary);
3299
3300         /*
3301                 u16 command
3302                 u32 length of the next item
3303                 zlib-compressed serialized NodeDefManager
3304         */
3305         writeU16(os, TOCLIENT_NODEDEF);
3306         std::ostringstream tmp_os(std::ios::binary);
3307         nodedef->serialize(tmp_os);
3308         std::ostringstream tmp_os2(std::ios::binary);
3309         compressZlib(tmp_os.str(), tmp_os2);
3310         os<<serializeLongString(tmp_os2.str());
3311
3312         // Make data buffer
3313         std::string s = os.str();
3314         infostream<<"Server::SendNodeDef(): Sending node definitions: size="
3315                         <<s.size()<<std::endl;
3316         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3317         // Send as reliable
3318         con.Send(peer_id, 0, data, true);
3319 }
3320
3321 /*
3322         Non-static send methods
3323 */
3324
3325 void Server::SendInventory(u16 peer_id)
3326 {
3327         DSTACK(__FUNCTION_NAME);
3328         
3329         ServerRemotePlayer* player =
3330                         static_cast<ServerRemotePlayer*>(m_env->getPlayer(peer_id));
3331         assert(player);
3332
3333         player->m_inventory_not_sent = false;
3334
3335         /*
3336                 Serialize it
3337         */
3338
3339         std::ostringstream os;
3340         //os.imbue(std::locale("C"));
3341
3342         player->inventory.serialize(os);
3343
3344         std::string s = os.str();
3345         
3346         SharedBuffer<u8> data(s.size()+2);
3347         writeU16(&data[0], TOCLIENT_INVENTORY);
3348         memcpy(&data[2], s.c_str(), s.size());
3349         
3350         // Send as reliable
3351         m_con.Send(peer_id, 0, data, true);
3352 }
3353
3354 void Server::SendWieldedItem(const ServerRemotePlayer* srp)
3355 {
3356         DSTACK(__FUNCTION_NAME);
3357
3358         assert(srp);
3359
3360         std::ostringstream os(std::ios_base::binary);
3361
3362         writeU16(os, TOCLIENT_PLAYERITEM);
3363         writeU16(os, 1);
3364         writeU16(os, srp->peer_id);
3365         os<<serializeString(srp->getWieldedItem().getItemString());
3366
3367         // Make data buffer
3368         std::string s = os.str();
3369         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3370
3371         m_con.SendToAll(0, data, true);
3372 }
3373
3374 void Server::SendPlayerItems()
3375 {
3376         DSTACK(__FUNCTION_NAME);
3377
3378         std::ostringstream os(std::ios_base::binary);
3379         core::list<Player *> players = m_env->getPlayers(true);
3380
3381         writeU16(os, TOCLIENT_PLAYERITEM);
3382         writeU16(os, players.size());
3383         core::list<Player *>::Iterator i;
3384         for(i = players.begin(); i != players.end(); ++i)
3385         {
3386                 Player *p = *i;
3387                 ServerRemotePlayer *srp =
3388                         static_cast<ServerRemotePlayer*>(p);
3389                 writeU16(os, p->peer_id);
3390                 os<<serializeString(srp->getWieldedItem().getItemString());
3391         }
3392
3393         // Make data buffer
3394         std::string s = os.str();
3395         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3396
3397         m_con.SendToAll(0, data, true);
3398 }
3399
3400 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
3401 {
3402         DSTACK(__FUNCTION_NAME);
3403         
3404         std::ostringstream os(std::ios_base::binary);
3405         u8 buf[12];
3406         
3407         // Write command
3408         writeU16(buf, TOCLIENT_CHAT_MESSAGE);
3409         os.write((char*)buf, 2);
3410         
3411         // Write length
3412         writeU16(buf, message.size());
3413         os.write((char*)buf, 2);
3414         
3415         // Write string
3416         for(u32 i=0; i<message.size(); i++)
3417         {
3418                 u16 w = message[i];
3419                 writeU16(buf, w);
3420                 os.write((char*)buf, 2);
3421         }
3422         
3423         // Make data buffer
3424         std::string s = os.str();
3425         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3426         // Send as reliable
3427         m_con.Send(peer_id, 0, data, true);
3428 }
3429
3430 void Server::BroadcastChatMessage(const std::wstring &message)
3431 {
3432         for(core::map<u16, RemoteClient*>::Iterator
3433                 i = m_clients.getIterator();
3434                 i.atEnd() == false; i++)
3435         {
3436                 // Get client and check that it is valid
3437                 RemoteClient *client = i.getNode()->getValue();
3438                 assert(client->peer_id == i.getNode()->getKey());
3439                 if(client->serialization_version == SER_FMT_VER_INVALID)
3440                         continue;
3441
3442                 SendChatMessage(client->peer_id, message);
3443         }
3444 }
3445
3446 void Server::SendPlayerHP(Player *player)
3447 {
3448         SendHP(m_con, player->peer_id, player->hp);
3449         static_cast<ServerRemotePlayer*>(player)->m_hp_not_sent = false;
3450 }
3451
3452 void Server::SendMovePlayer(Player *player)
3453 {
3454         DSTACK(__FUNCTION_NAME);
3455         std::ostringstream os(std::ios_base::binary);
3456
3457         writeU16(os, TOCLIENT_MOVE_PLAYER);
3458         writeV3F1000(os, player->getPosition());
3459         writeF1000(os, player->getPitch());
3460         writeF1000(os, player->getYaw());
3461         
3462         {
3463                 v3f pos = player->getPosition();
3464                 f32 pitch = player->getPitch();
3465                 f32 yaw = player->getYaw();
3466                 infostream<<"Server sending TOCLIENT_MOVE_PLAYER"
3467                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3468                                 <<" pitch="<<pitch
3469                                 <<" yaw="<<yaw
3470                                 <<std::endl;
3471         }
3472
3473         // Make data buffer
3474         std::string s = os.str();
3475         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3476         // Send as reliable
3477         m_con.Send(player->peer_id, 0, data, true);
3478 }
3479
3480 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
3481         core::list<u16> *far_players, float far_d_nodes)
3482 {
3483         float maxd = far_d_nodes*BS;
3484         v3f p_f = intToFloat(p, BS);
3485
3486         // Create packet
3487         u32 replysize = 8;
3488         SharedBuffer<u8> reply(replysize);
3489         writeU16(&reply[0], TOCLIENT_REMOVENODE);
3490         writeS16(&reply[2], p.X);
3491         writeS16(&reply[4], p.Y);
3492         writeS16(&reply[6], p.Z);
3493
3494         for(core::map<u16, RemoteClient*>::Iterator
3495                 i = m_clients.getIterator();
3496                 i.atEnd() == false; i++)
3497         {
3498                 // Get client and check that it is valid
3499                 RemoteClient *client = i.getNode()->getValue();
3500                 assert(client->peer_id == i.getNode()->getKey());
3501                 if(client->serialization_version == SER_FMT_VER_INVALID)
3502                         continue;
3503
3504                 // Don't send if it's the same one
3505                 if(client->peer_id == ignore_id)
3506                         continue;
3507                 
3508                 if(far_players)
3509                 {
3510                         // Get player
3511                         Player *player = m_env->getPlayer(client->peer_id);
3512                         if(player)
3513                         {
3514                                 // If player is far away, only set modified blocks not sent
3515                                 v3f player_pos = player->getPosition();
3516                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3517                                 {
3518                                         far_players->push_back(client->peer_id);
3519                                         continue;
3520                                 }
3521                         }
3522                 }
3523
3524                 // Send as reliable
3525                 m_con.Send(client->peer_id, 0, reply, true);
3526         }
3527 }
3528
3529 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
3530                 core::list<u16> *far_players, float far_d_nodes)
3531 {
3532         float maxd = far_d_nodes*BS;
3533         v3f p_f = intToFloat(p, BS);
3534
3535         for(core::map<u16, RemoteClient*>::Iterator
3536                 i = m_clients.getIterator();
3537                 i.atEnd() == false; i++)
3538         {
3539                 // Get client and check that it is valid
3540                 RemoteClient *client = i.getNode()->getValue();
3541                 assert(client->peer_id == i.getNode()->getKey());
3542                 if(client->serialization_version == SER_FMT_VER_INVALID)
3543                         continue;
3544
3545                 // Don't send if it's the same one
3546                 if(client->peer_id == ignore_id)
3547                         continue;
3548
3549                 if(far_players)
3550                 {
3551                         // Get player
3552                         Player *player = m_env->getPlayer(client->peer_id);
3553                         if(player)
3554                         {
3555                                 // If player is far away, only set modified blocks not sent
3556                                 v3f player_pos = player->getPosition();
3557                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3558                                 {
3559                                         far_players->push_back(client->peer_id);
3560                                         continue;
3561                                 }
3562                         }
3563                 }
3564
3565                 // Create packet
3566                 u32 replysize = 8 + MapNode::serializedLength(client->serialization_version);
3567                 SharedBuffer<u8> reply(replysize);
3568                 writeU16(&reply[0], TOCLIENT_ADDNODE);
3569                 writeS16(&reply[2], p.X);
3570                 writeS16(&reply[4], p.Y);
3571                 writeS16(&reply[6], p.Z);
3572                 n.serialize(&reply[8], client->serialization_version);
3573
3574                 // Send as reliable
3575                 m_con.Send(client->peer_id, 0, reply, true);
3576         }
3577 }
3578
3579 void Server::setBlockNotSent(v3s16 p)
3580 {
3581         for(core::map<u16, RemoteClient*>::Iterator
3582                 i = m_clients.getIterator();
3583                 i.atEnd()==false; i++)
3584         {
3585                 RemoteClient *client = i.getNode()->getValue();
3586                 client->SetBlockNotSent(p);
3587         }
3588 }
3589
3590 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
3591 {
3592         DSTACK(__FUNCTION_NAME);
3593
3594         v3s16 p = block->getPos();
3595         
3596 #if 0
3597         // Analyze it a bit
3598         bool completely_air = true;
3599         for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
3600         for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
3601         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
3602         {
3603                 if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
3604                 {
3605                         completely_air = false;
3606                         x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
3607                 }
3608         }
3609
3610         // Print result
3611         infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
3612         if(completely_air)
3613                 infostream<<"[completely air] ";
3614         infostream<<std::endl;
3615 #endif
3616
3617         /*
3618                 Create a packet with the block in the right format
3619         */
3620         
3621         std::ostringstream os(std::ios_base::binary);
3622         block->serialize(os, ver, false);
3623         std::string s = os.str();
3624         SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
3625
3626         u32 replysize = 8 + blockdata.getSize();
3627         SharedBuffer<u8> reply(replysize);
3628         writeU16(&reply[0], TOCLIENT_BLOCKDATA);
3629         writeS16(&reply[2], p.X);
3630         writeS16(&reply[4], p.Y);
3631         writeS16(&reply[6], p.Z);
3632         memcpy(&reply[8], *blockdata, blockdata.getSize());
3633
3634         /*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
3635                         <<":  \tpacket size: "<<replysize<<std::endl;*/
3636         
3637         /*
3638                 Send packet
3639         */
3640         m_con.Send(peer_id, 1, reply, true);
3641 }
3642
3643 void Server::SendBlocks(float dtime)
3644 {
3645         DSTACK(__FUNCTION_NAME);
3646
3647         JMutexAutoLock envlock(m_env_mutex);
3648         JMutexAutoLock conlock(m_con_mutex);
3649
3650         //TimeTaker timer("Server::SendBlocks");
3651
3652         core::array<PrioritySortedBlockTransfer> queue;
3653
3654         s32 total_sending = 0;
3655         
3656         {
3657                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
3658
3659                 for(core::map<u16, RemoteClient*>::Iterator
3660                         i = m_clients.getIterator();
3661                         i.atEnd() == false; i++)
3662                 {
3663                         RemoteClient *client = i.getNode()->getValue();
3664                         assert(client->peer_id == i.getNode()->getKey());
3665
3666                         // If definitions and textures have not been sent, don't
3667                         // send MapBlocks either
3668                         if(!client->definitions_sent)
3669                                 continue;
3670
3671                         total_sending += client->SendingCount();
3672                         
3673                         if(client->serialization_version == SER_FMT_VER_INVALID)
3674                                 continue;
3675                         
3676                         client->GetNextBlocks(this, dtime, queue);
3677                 }
3678         }
3679
3680         // Sort.
3681         // Lowest priority number comes first.
3682         // Lowest is most important.
3683         queue.sort();
3684
3685         for(u32 i=0; i<queue.size(); i++)
3686         {
3687                 //TODO: Calculate limit dynamically
3688                 if(total_sending >= g_settings->getS32
3689                                 ("max_simultaneous_block_sends_server_total"))
3690                         break;
3691                 
3692                 PrioritySortedBlockTransfer q = queue[i];
3693
3694                 MapBlock *block = NULL;
3695                 try
3696                 {
3697                         block = m_env->getMap().getBlockNoCreate(q.pos);
3698                 }
3699                 catch(InvalidPositionException &e)
3700                 {
3701                         continue;
3702                 }
3703
3704                 RemoteClient *client = getClient(q.peer_id);
3705
3706                 SendBlockNoLock(q.peer_id, block, client->serialization_version);
3707
3708                 client->SentBlock(q.pos);
3709
3710                 total_sending++;
3711         }
3712 }
3713
3714 void Server::PrepareTextures() {
3715         DSTACK(__FUNCTION_NAME);
3716
3717         infostream<<"Server::PrepareTextures(): Calculate sha1 sums of textures"<<std::endl;
3718
3719         for(core::list<ModSpec>::Iterator i = m_mods.begin();
3720                                         i != m_mods.end(); i++){
3721                         const ModSpec &mod = *i;
3722                         std::string texturepath = mod.path + DIR_DELIM + "textures";
3723                         std::vector<fs::DirListNode> dirlist = fs::GetDirListing(texturepath);
3724                         for(u32 j=0; j<dirlist.size(); j++){
3725                                 if(dirlist[j].dir) // Ignode dirs
3726                                         continue;
3727                                 std::string tname = dirlist[j].name;
3728                                 // if name contains illegal characters, ignore the texture
3729                                 if(!string_allowed(tname, TEXTURENAME_ALLOWED_CHARS)){
3730                                         errorstream<<"Server: ignoring illegal texture name: \""
3731                                                         <<tname<<"\""<<std::endl;
3732                                         continue;
3733                                 }
3734                                 std::string tpath = texturepath + DIR_DELIM + tname;
3735                                 // Read data
3736                                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
3737                                 if(fis.good() == false){
3738                                         errorstream<<"Server::PrepareTextures(): Could not open \""
3739                                                         <<tname<<"\" for reading"<<std::endl;
3740                                         continue;
3741                                 }
3742                                 std::ostringstream tmp_os(std::ios_base::binary);
3743                                 bool bad = false;
3744                                 for(;;){
3745                                         char buf[1024];
3746                                         fis.read(buf, 1024);
3747                                         std::streamsize len = fis.gcount();
3748                                         tmp_os.write(buf, len);
3749                                         if(fis.eof())
3750                                                 break;
3751                                         if(!fis.good()){
3752                                                 bad = true;
3753                                                 break;
3754                                         }
3755                                 }
3756                                 if(bad){
3757                                         errorstream<<"Server::PrepareTextures(): Failed to read \""
3758                                                         <<tname<<"\""<<std::endl;
3759                                         continue;
3760                                 }
3761                                 if(tmp_os.str().length() == 0){
3762                                         errorstream<<"Server::PrepareTextures(): Empty file \""
3763                                                         <<tpath<<"\""<<std::endl;
3764                                         continue;
3765                                 }
3766
3767                                 SHA1 sha1;
3768                                 sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
3769
3770                                 unsigned char *digest = sha1.getDigest();
3771                                 std::string digest_string = base64_encode(digest, 20);
3772
3773                                 free(digest);
3774
3775                                 // Put in list
3776                                 this->m_Textures[tname] = TextureInformation(tpath,digest_string);
3777                                 infostream<<"Server::PrepareTextures(): added sha1 for "<< tname <<std::endl;
3778                         }
3779         }
3780 }
3781
3782 struct SendableTextureAnnouncement
3783         {
3784                 std::string name;
3785                 std::string sha1_digest;
3786
3787                 SendableTextureAnnouncement(const std::string name_="",
3788                                 const std::string sha1_digest_=""):
3789                         name(name_),
3790                         sha1_digest(sha1_digest_)
3791                 {
3792                 }
3793         };
3794
3795 void Server::SendTextureAnnouncement(u16 peer_id){
3796         DSTACK(__FUNCTION_NAME);
3797
3798         infostream<<"Server::SendTextureAnnouncement()"<<std::endl;
3799
3800         core::list<SendableTextureAnnouncement> texture_announcements;
3801
3802         for (std::map<std::string,TextureInformation>::iterator i = m_Textures.begin();i != m_Textures.end(); i++ ) {
3803
3804                 // Put in list
3805                 texture_announcements.push_back(
3806                                 SendableTextureAnnouncement(i->first, i->second.sha1_digest));
3807         }
3808
3809         //send announcements
3810
3811         /*
3812                 u16 command
3813                 u32 number of textures
3814                 for each texture {
3815                         u16 length of name
3816                         string name
3817                         u16 length of digest string
3818                         string sha1_digest
3819                 }
3820         */
3821         std::ostringstream os(std::ios_base::binary);
3822
3823         writeU16(os,    TOCLIENT_ANNOUNCE_TEXTURES);
3824         writeU16(os, texture_announcements.size());
3825
3826         for(core::list<SendableTextureAnnouncement>::Iterator
3827                         j = texture_announcements.begin();
3828                         j != texture_announcements.end(); j++){
3829                 os<<serializeString(j->name);
3830                 os<<serializeString(j->sha1_digest);
3831         }
3832
3833         // Make data buffer
3834         std::string s = os.str();
3835         infostream<<"Server::SendTextureAnnouncement(): Send to client"<<std::endl;
3836         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3837
3838         // Send as reliable
3839         m_con.Send(peer_id, 0, data, true);
3840
3841 }
3842
3843 struct SendableTexture
3844 {
3845         std::string name;
3846         std::string path;
3847         std::string data;
3848
3849         SendableTexture(const std::string &name_="", const std::string path_="",
3850                         const std::string &data_=""):
3851                 name(name_),
3852                 path(path_),
3853                 data(data_)
3854         {}
3855 };
3856
3857 void Server::SendTexturesRequested(u16 peer_id,core::list<TextureRequest> tosend) {
3858         DSTACK(__FUNCTION_NAME);
3859
3860         infostream<<"Server::SendTexturesRequested(): Sending textures to client"<<std::endl;
3861
3862         /* Read textures */
3863
3864         // Put 5kB in one bunch (this is not accurate)
3865         u32 bytes_per_bunch = 5000;
3866
3867         core::array< core::list<SendableTexture> > texture_bunches;
3868         texture_bunches.push_back(core::list<SendableTexture>());
3869
3870         u32 texture_size_bunch_total = 0;
3871
3872         for(core::list<TextureRequest>::Iterator i = tosend.begin(); i != tosend.end(); i++) {
3873                 if(m_Textures.find(i->name) == m_Textures.end()){
3874                         errorstream<<"Server::SendTexturesRequested(): Client asked for "
3875                                         <<"unknown texture \""<<(i->name)<<"\""<<std::endl;
3876                         continue;
3877                 }
3878
3879                 //TODO get path + name
3880                 std::string tpath = m_Textures[(*i).name].path;
3881
3882                 // Read data
3883                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
3884                 if(fis.good() == false){
3885                         errorstream<<"Server::SendTexturesRequested(): Could not open \""
3886                                         <<tpath<<"\" for reading"<<std::endl;
3887                         continue;
3888                 }
3889                 std::ostringstream tmp_os(std::ios_base::binary);
3890                 bool bad = false;
3891                 for(;;){
3892                         char buf[1024];
3893                         fis.read(buf, 1024);
3894                         std::streamsize len = fis.gcount();
3895                         tmp_os.write(buf, len);
3896                         texture_size_bunch_total += len;
3897                         if(fis.eof())
3898                                 break;
3899                         if(!fis.good()){
3900                                 bad = true;
3901                                 break;
3902                         }
3903                 }
3904                 if(bad){
3905                         errorstream<<"Server::SendTexturesRequested(): Failed to read \""
3906                                         <<(*i).name<<"\""<<std::endl;
3907                         continue;
3908                 }
3909                 /*infostream<<"Server::SendTexturesRequested(): Loaded \""
3910                                 <<tname<<"\""<<std::endl;*/
3911                 // Put in list
3912                 texture_bunches[texture_bunches.size()-1].push_back(
3913                                 SendableTexture((*i).name, tpath, tmp_os.str()));
3914
3915                 // Start next bunch if got enough data
3916                 if(texture_size_bunch_total >= bytes_per_bunch){
3917                         texture_bunches.push_back(core::list<SendableTexture>());
3918                         texture_size_bunch_total = 0;
3919                 }
3920
3921         }
3922
3923         /* Create and send packets */
3924
3925                 u32 num_bunches = texture_bunches.size();
3926                 for(u32 i=0; i<num_bunches; i++)
3927                 {
3928                         /*
3929                                 u16 command
3930                                 u16 total number of texture bunches
3931                                 u16 index of this bunch
3932                                 u32 number of textures in this bunch
3933                                 for each texture {
3934                                         u16 length of name
3935                                         string name
3936                                         u32 length of data
3937                                         data
3938                                 }
3939                         */
3940                         std::ostringstream os(std::ios_base::binary);
3941
3942                         writeU16(os, TOCLIENT_TEXTURES);
3943                         writeU16(os, num_bunches);
3944                         writeU16(os, i);
3945                         writeU32(os, texture_bunches[i].size());
3946
3947                         for(core::list<SendableTexture>::Iterator
3948                                         j = texture_bunches[i].begin();
3949                                         j != texture_bunches[i].end(); j++){
3950                                 os<<serializeString(j->name);
3951                                 os<<serializeLongString(j->data);
3952                         }
3953
3954                         // Make data buffer
3955                         std::string s = os.str();
3956                         infostream<<"Server::SendTexturesRequested(): bunch "<<i<<"/"<<num_bunches
3957                                         <<" textures="<<texture_bunches[i].size()
3958                                         <<" size=" <<s.size()<<std::endl;
3959                         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3960                         // Send as reliable
3961                         m_con.Send(peer_id, 0, data, true);
3962                 }
3963
3964
3965 }
3966
3967 /*
3968         Something random
3969 */
3970
3971 void Server::HandlePlayerHP(Player *player, s16 damage)
3972 {
3973         ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
3974
3975         if(srp->m_respawn_active)
3976                 return;
3977         
3978         if(player->hp > damage)
3979         {
3980                 if(damage != 0){
3981                         player->hp -= damage;
3982                         SendPlayerHP(player);
3983                 }
3984                 return;
3985         }
3986
3987         infostream<<"Server::HandlePlayerHP(): Player "
3988                         <<player->getName()<<" dies"<<std::endl;
3989         
3990         player->hp = 0;
3991         
3992         // Trigger scripted stuff
3993         scriptapi_on_dieplayer(m_lua, srp);
3994         
3995         // Handle players that are not connected
3996         if(player->peer_id == PEER_ID_INEXISTENT){
3997                 RespawnPlayer(player);
3998                 return;
3999         }
4000
4001         SendPlayerHP(player);
4002         
4003         RemoteClient *client = getClient(player->peer_id);
4004         if(client->net_proto_version >= 3)
4005         {
4006                 SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
4007                 srp->m_removed = true;
4008                 srp->m_respawn_active = true;
4009         }
4010         else
4011         {
4012                 RespawnPlayer(player);
4013         }
4014 }
4015
4016 void Server::RespawnPlayer(Player *player)
4017 {
4018         player->hp = 20;
4019         ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
4020         bool repositioned = scriptapi_on_respawnplayer(m_lua, srp);
4021         if(!repositioned){
4022                 v3f pos = findSpawnPos(m_env->getServerMap());
4023                 player->setPosition(pos);
4024                 srp->m_last_good_position = pos;
4025                 srp->m_last_good_position_age = 0;
4026         }
4027         SendMovePlayer(player);
4028         SendPlayerHP(player);
4029 }
4030
4031 void Server::UpdateCrafting(u16 peer_id)
4032 {
4033         DSTACK(__FUNCTION_NAME);
4034         
4035         Player* player = m_env->getPlayer(peer_id);
4036         assert(player);
4037
4038         // Get a preview for crafting
4039         ItemStack preview;
4040         // No crafting in creative mode
4041         if(g_settings->getBool("creative_mode") == false)
4042                 getCraftingResult(&player->inventory, preview, false, this);
4043
4044         // Put the new preview in
4045         InventoryList *plist = player->inventory.getList("craftpreview");
4046         assert(plist);
4047         assert(plist->getSize() >= 1);
4048         plist->changeItem(0, preview);
4049 }
4050
4051 RemoteClient* Server::getClient(u16 peer_id)
4052 {
4053         DSTACK(__FUNCTION_NAME);
4054         //JMutexAutoLock lock(m_con_mutex);
4055         core::map<u16, RemoteClient*>::Node *n;
4056         n = m_clients.find(peer_id);
4057         // A client should exist for all peers
4058         assert(n != NULL);
4059         return n->getValue();
4060 }
4061
4062 std::wstring Server::getStatusString()
4063 {
4064         std::wostringstream os(std::ios_base::binary);
4065         os<<L"# Server: ";
4066         // Version
4067         os<<L"version="<<narrow_to_wide(VERSION_STRING);
4068         // Uptime
4069         os<<L", uptime="<<m_uptime.get();
4070         // Information about clients
4071         os<<L", clients={";
4072         for(core::map<u16, RemoteClient*>::Iterator
4073                 i = m_clients.getIterator();
4074                 i.atEnd() == false; i++)
4075         {
4076                 // Get client and check that it is valid
4077                 RemoteClient *client = i.getNode()->getValue();
4078                 assert(client->peer_id == i.getNode()->getKey());
4079                 if(client->serialization_version == SER_FMT_VER_INVALID)
4080                         continue;
4081                 // Get player
4082                 Player *player = m_env->getPlayer(client->peer_id);
4083                 // Get name of player
4084                 std::wstring name = L"unknown";
4085                 if(player != NULL)
4086                         name = narrow_to_wide(player->getName());
4087                 // Add name to information string
4088                 os<<name<<L",";
4089         }
4090         os<<L"}";
4091         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
4092                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
4093         if(g_settings->get("motd") != "")
4094                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
4095         return os.str();
4096 }
4097
4098 void Server::setPlayerPassword(const std::string &name, const std::wstring &password)
4099 {
4100         // Add player to auth manager
4101         if(m_authmanager.exists(name) == false)
4102         {
4103                 infostream<<"Server: adding player "<<name
4104                                 <<" to auth manager"<<std::endl;
4105                 m_authmanager.add(name);
4106                 m_authmanager.setPrivs(name,
4107                         stringToPrivs(g_settings->get("default_privs")));
4108         }
4109         // Change password and save
4110         m_authmanager.setPassword(name, translatePassword(name, password));
4111         m_authmanager.save();
4112 }
4113
4114 // Saves g_settings to configpath given at initialization
4115 void Server::saveConfig()
4116 {
4117         if(m_configpath != "")
4118                 g_settings->updateConfigFile(m_configpath.c_str());
4119 }
4120
4121 void Server::notifyPlayer(const char *name, const std::wstring msg)
4122 {
4123         Player *player = m_env->getPlayer(name);
4124         if(!player)
4125                 return;
4126         SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
4127 }
4128
4129 void Server::notifyPlayers(const std::wstring msg)
4130 {
4131         BroadcastChatMessage(msg);
4132 }
4133
4134 void Server::queueBlockEmerge(v3s16 blockpos, bool allow_generate)
4135 {
4136         u8 flags = 0;
4137         if(!allow_generate)
4138                 flags |= BLOCK_EMERGE_FLAG_FROMDISK;
4139         m_emerge_queue.addBlock(PEER_ID_INEXISTENT, blockpos, flags);
4140 }
4141
4142 // IGameDef interface
4143 // Under envlock
4144 IItemDefManager* Server::getItemDefManager()
4145 {
4146         return m_itemdef;
4147 }
4148 INodeDefManager* Server::getNodeDefManager()
4149 {
4150         return m_nodedef;
4151 }
4152 ICraftDefManager* Server::getCraftDefManager()
4153 {
4154         return m_craftdef;
4155 }
4156 ITextureSource* Server::getTextureSource()
4157 {
4158         return NULL;
4159 }
4160 u16 Server::allocateUnknownNodeId(const std::string &name)
4161 {
4162         return m_nodedef->allocateDummy(name);
4163 }
4164
4165 IWritableItemDefManager* Server::getWritableItemDefManager()
4166 {
4167         return m_itemdef;
4168 }
4169 IWritableNodeDefManager* Server::getWritableNodeDefManager()
4170 {
4171         return m_nodedef;
4172 }
4173 IWritableCraftDefManager* Server::getWritableCraftDefManager()
4174 {
4175         return m_craftdef;
4176 }
4177
4178 const ModSpec* Server::getModSpec(const std::string &modname)
4179 {
4180         for(core::list<ModSpec>::Iterator i = m_mods.begin();
4181                         i != m_mods.end(); i++){
4182                 const ModSpec &mod = *i;
4183                 if(mod.name == modname)
4184                         return &mod;
4185         }
4186         return NULL;
4187 }
4188
4189 v3f findSpawnPos(ServerMap &map)
4190 {
4191         //return v3f(50,50,50)*BS;
4192
4193         v3s16 nodepos;
4194         
4195 #if 0
4196         nodepos = v2s16(0,0);
4197         groundheight = 20;
4198 #endif
4199
4200 #if 1
4201         // Try to find a good place a few times
4202         for(s32 i=0; i<1000; i++)
4203         {
4204                 s32 range = 1 + i;
4205                 // We're going to try to throw the player to this position
4206                 v2s16 nodepos2d = v2s16(-range + (myrand()%(range*2)),
4207                                 -range + (myrand()%(range*2)));
4208                 //v2s16 sectorpos = getNodeSectorPos(nodepos2d);
4209                 // Get ground height at point (fallbacks to heightmap function)
4210                 s16 groundheight = map.findGroundLevel(nodepos2d);
4211                 // Don't go underwater
4212                 if(groundheight < WATER_LEVEL)
4213                 {
4214                         //infostream<<"-> Underwater"<<std::endl;
4215                         continue;
4216                 }
4217                 // Don't go to high places
4218                 if(groundheight > WATER_LEVEL + 4)
4219                 {
4220                         //infostream<<"-> Underwater"<<std::endl;
4221                         continue;
4222                 }
4223                 
4224                 nodepos = v3s16(nodepos2d.X, groundheight-2, nodepos2d.Y);
4225                 bool is_good = false;
4226                 s32 air_count = 0;
4227                 for(s32 i=0; i<10; i++){
4228                         v3s16 blockpos = getNodeBlockPos(nodepos);
4229                         map.emergeBlock(blockpos, true);
4230                         MapNode n = map.getNodeNoEx(nodepos);
4231                         if(n.getContent() == CONTENT_AIR){
4232                                 air_count++;
4233                                 if(air_count >= 2){
4234                                         is_good = true;
4235                                         nodepos.Y -= 1;
4236                                         break;
4237                                 }
4238                         }
4239                         nodepos.Y++;
4240                 }
4241                 if(is_good){
4242                         // Found a good place
4243                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
4244                         break;
4245                 }
4246         }
4247 #endif
4248         
4249         return intToFloat(nodepos, BS);
4250 }
4251
4252 ServerRemotePlayer *Server::emergePlayer(const char *name, u16 peer_id)
4253 {
4254         /*
4255                 Try to get an existing player
4256         */
4257         ServerRemotePlayer *player =
4258                         static_cast<ServerRemotePlayer*>(m_env->getPlayer(name));
4259         if(player != NULL)
4260         {
4261                 // If player is already connected, cancel
4262                 if(player->peer_id != 0)
4263                 {
4264                         infostream<<"emergePlayer(): Player already connected"<<std::endl;
4265                         return NULL;
4266                 }
4267
4268                 // Got one.
4269                 player->peer_id = peer_id;
4270                 
4271                 // Reset inventory to creative if in creative mode
4272                 if(g_settings->getBool("creative_mode"))
4273                 {
4274                         // Warning: double code below
4275                         // Backup actual inventory
4276                         player->inventory_backup = new Inventory(m_itemdef);
4277                         *(player->inventory_backup) = player->inventory;
4278                         // Set creative inventory
4279                         player->resetInventory();
4280                         scriptapi_get_creative_inventory(m_lua, player);
4281                 }
4282
4283                 return player;
4284         }
4285
4286         /*
4287                 If player with the wanted peer_id already exists, cancel.
4288         */
4289         if(m_env->getPlayer(peer_id) != NULL)
4290         {
4291                 infostream<<"emergePlayer(): Player with wrong name but same"
4292                                 " peer_id already exists"<<std::endl;
4293                 return NULL;
4294         }
4295         
4296         /*
4297                 Create a new player
4298         */
4299         {
4300                 /* Set player position */
4301                 
4302                 infostream<<"Server: Finding spawn place for player \""
4303                                 <<name<<"\""<<std::endl;
4304
4305                 v3f pos = findSpawnPos(m_env->getServerMap());
4306
4307                 player = new ServerRemotePlayer(m_env, pos, peer_id, name);
4308
4309                 /* Add player to environment */
4310                 m_env->addPlayer(player);
4311
4312                 /* Run scripts */
4313                 ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
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