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