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