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