Tune caves
[oweals/minetest.git] / src / server.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include "utility.h"
22 #include <iostream>
23 #include <queue>
24 #include "clientserver.h"
25 #include "map.h"
26 #include "jmutexautolock.h"
27 #include "main.h"
28 #include "constants.h"
29 #include "voxel.h"
30 #include "config.h"
31 #include "servercommand.h"
32 #include "filesys.h"
33 #include "content_mapnode.h"
34 #include "content_nodemeta.h"
35 #include "mapblock.h"
36 #include "serverobject.h"
37 #include "settings.h"
38 #include "profiler.h"
39 #include "log.h"
40 #include "script.h"
41 #include "scriptapi.h"
42 #include "nodedef.h"
43 #include "itemdef.h"
44 #include "craftdef.h"
45 #include "mapgen.h"
46 #include "content_abm.h"
47 #include "mods.h"
48 #include "sha1.h"
49 #include "base64.h"
50 #include "tool.h"
51 #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                 // Don't send too many at a time
1693                 //u32 count = 0;
1694
1695                 // Single change sending is disabled if queue size is not small
1696                 bool disable_single_change_sending = false;
1697                 if(m_unsent_map_edit_queue.size() >= 4)
1698                         disable_single_change_sending = true;
1699
1700                 int event_count = m_unsent_map_edit_queue.size();
1701
1702                 // We'll log the amount of each
1703                 Profiler prof;
1704
1705                 while(m_unsent_map_edit_queue.size() != 0)
1706                 {
1707                         MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
1708                         
1709                         // Players far away from the change are stored here.
1710                         // Instead of sending the changes, MapBlocks are set not sent
1711                         // for them.
1712                         core::list<u16> far_players;
1713
1714                         if(event->type == MEET_ADDNODE)
1715                         {
1716                                 //infostream<<"Server: MEET_ADDNODE"<<std::endl;
1717                                 prof.add("MEET_ADDNODE", 1);
1718                                 if(disable_single_change_sending)
1719                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
1720                                                         &far_players, 5);
1721                                 else
1722                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
1723                                                         &far_players, 30);
1724                         }
1725                         else if(event->type == MEET_REMOVENODE)
1726                         {
1727                                 //infostream<<"Server: MEET_REMOVENODE"<<std::endl;
1728                                 prof.add("MEET_REMOVENODE", 1);
1729                                 if(disable_single_change_sending)
1730                                         sendRemoveNode(event->p, event->already_known_by_peer,
1731                                                         &far_players, 5);
1732                                 else
1733                                         sendRemoveNode(event->p, event->already_known_by_peer,
1734                                                         &far_players, 30);
1735                         }
1736                         else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
1737                         {
1738                                 infostream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
1739                                 prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
1740                                 setBlockNotSent(event->p);
1741                         }
1742                         else if(event->type == MEET_OTHER)
1743                         {
1744                                 infostream<<"Server: MEET_OTHER"<<std::endl;
1745                                 prof.add("MEET_OTHER", 1);
1746                                 for(core::map<v3s16, bool>::Iterator
1747                                                 i = event->modified_blocks.getIterator();
1748                                                 i.atEnd()==false; i++)
1749                                 {
1750                                         v3s16 p = i.getNode()->getKey();
1751                                         setBlockNotSent(p);
1752                                 }
1753                         }
1754                         else
1755                         {
1756                                 prof.add("unknown", 1);
1757                                 infostream<<"WARNING: Server: Unknown MapEditEvent "
1758                                                 <<((u32)event->type)<<std::endl;
1759                         }
1760                         
1761                         /*
1762                                 Set blocks not sent to far players
1763                         */
1764                         if(far_players.size() > 0)
1765                         {
1766                                 // Convert list format to that wanted by SetBlocksNotSent
1767                                 core::map<v3s16, MapBlock*> modified_blocks2;
1768                                 for(core::map<v3s16, bool>::Iterator
1769                                                 i = event->modified_blocks.getIterator();
1770                                                 i.atEnd()==false; i++)
1771                                 {
1772                                         v3s16 p = i.getNode()->getKey();
1773                                         modified_blocks2.insert(p,
1774                                                         m_env->getMap().getBlockNoCreateNoEx(p));
1775                                 }
1776                                 // Set blocks not sent
1777                                 for(core::list<u16>::Iterator
1778                                                 i = far_players.begin();
1779                                                 i != far_players.end(); i++)
1780                                 {
1781                                         u16 peer_id = *i;
1782                                         RemoteClient *client = getClient(peer_id);
1783                                         if(client==NULL)
1784                                                 continue;
1785                                         client->SetBlocksNotSent(modified_blocks2);
1786                                 }
1787                         }
1788
1789                         delete event;
1790
1791                         /*// Don't send too many at a time
1792                         count++;
1793                         if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
1794                                 break;*/
1795                 }
1796
1797                 if(event_count >= 5){
1798                         infostream<<"Server: MapEditEvents:"<<std::endl;
1799                         prof.print(infostream);
1800                 } else if(event_count != 0){
1801                         verbosestream<<"Server: MapEditEvents:"<<std::endl;
1802                         prof.print(verbosestream);
1803                 }
1804                 
1805         }
1806
1807         /*
1808                 Trigger emergethread (it somehow gets to a non-triggered but
1809                 bysy state sometimes)
1810         */
1811         {
1812                 float &counter = m_emergethread_trigger_timer;
1813                 counter += dtime;
1814                 if(counter >= 2.0)
1815                 {
1816                         counter = 0.0;
1817                         
1818                         m_emergethread.trigger();
1819                 }
1820         }
1821
1822         // Save map, players and auth stuff
1823         {
1824                 float &counter = m_savemap_timer;
1825                 counter += dtime;
1826                 if(counter >= g_settings->getFloat("server_map_save_interval"))
1827                 {
1828                         counter = 0.0;
1829                         JMutexAutoLock lock(m_env_mutex);
1830
1831                         ScopeProfiler sp(g_profiler, "Server: saving stuff");
1832
1833                         // Auth stuff
1834                         if(m_authmanager.isModified())
1835                                 m_authmanager.save();
1836
1837                         //Ban stuff
1838                         if(m_banmanager.isModified())
1839                                 m_banmanager.save();
1840                         
1841                         // Save changed parts of map
1842                         m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
1843
1844                         // Save players
1845                         m_env->serializePlayers(m_path_world);
1846                         
1847                         // Save environment metadata
1848                         m_env->saveMeta(m_path_world);
1849                 }
1850         }
1851 }
1852
1853 void Server::Receive()
1854 {
1855         DSTACK(__FUNCTION_NAME);
1856         SharedBuffer<u8> data;
1857         u16 peer_id;
1858         u32 datasize;
1859         try{
1860                 {
1861                         JMutexAutoLock conlock(m_con_mutex);
1862                         datasize = m_con.Receive(peer_id, data);
1863                 }
1864
1865                 // This has to be called so that the client list gets synced
1866                 // with the peer list of the connection
1867                 handlePeerChanges();
1868
1869                 ProcessData(*data, datasize, peer_id);
1870         }
1871         catch(con::InvalidIncomingDataException &e)
1872         {
1873                 infostream<<"Server::Receive(): "
1874                                 "InvalidIncomingDataException: what()="
1875                                 <<e.what()<<std::endl;
1876         }
1877         catch(con::PeerNotFoundException &e)
1878         {
1879                 //NOTE: This is not needed anymore
1880                 
1881                 // The peer has been disconnected.
1882                 // Find the associated player and remove it.
1883
1884                 /*JMutexAutoLock envlock(m_env_mutex);
1885
1886                 infostream<<"ServerThread: peer_id="<<peer_id
1887                                 <<" has apparently closed connection. "
1888                                 <<"Removing player."<<std::endl;
1889
1890                 m_env->removePlayer(peer_id);*/
1891         }
1892 }
1893
1894 void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
1895 {
1896         DSTACK(__FUNCTION_NAME);
1897         // Environment is locked first.
1898         JMutexAutoLock envlock(m_env_mutex);
1899         JMutexAutoLock conlock(m_con_mutex);
1900         
1901         ScopeProfiler sp(g_profiler, "Server::ProcessData");
1902         
1903         try{
1904                 Address address = m_con.GetPeerAddress(peer_id);
1905                 std::string addr_s = address.serializeString();
1906
1907                 // drop player if is ip is banned
1908                 if(m_banmanager.isIpBanned(addr_s)){
1909                         infostream<<"Server: A banned client tried to connect from "
1910                                         <<addr_s<<"; banned name was "
1911                                         <<m_banmanager.getBanName(addr_s)<<std::endl;
1912                         // This actually doesn't seem to transfer to the client
1913                         SendAccessDenied(m_con, peer_id,
1914                                         L"Your ip is banned. Banned name was "
1915                                         +narrow_to_wide(m_banmanager.getBanName(addr_s)));
1916                         m_con.DeletePeer(peer_id);
1917                         return;
1918                 }
1919         }
1920         catch(con::PeerNotFoundException &e)
1921         {
1922                 infostream<<"Server::ProcessData(): Cancelling: peer "
1923                                 <<peer_id<<" not found"<<std::endl;
1924                 return;
1925         }
1926         
1927         std::string addr_s = m_con.GetPeerAddress(peer_id).serializeString();
1928
1929         u8 peer_ser_ver = getClient(peer_id)->serialization_version;
1930
1931         try
1932         {
1933
1934         if(datasize < 2)
1935                 return;
1936
1937         ToServerCommand command = (ToServerCommand)readU16(&data[0]);
1938         
1939         if(command == TOSERVER_INIT)
1940         {
1941                 // [0] u16 TOSERVER_INIT
1942                 // [2] u8 SER_FMT_VER_HIGHEST
1943                 // [3] u8[20] player_name
1944                 // [23] u8[28] password <--- can be sent without this, from old versions
1945
1946                 if(datasize < 2+1+PLAYERNAME_SIZE)
1947                         return;
1948
1949                 verbosestream<<"Server: Got TOSERVER_INIT from "
1950                                 <<peer_id<<std::endl;
1951
1952                 // First byte after command is maximum supported
1953                 // serialization version
1954                 u8 client_max = data[2];
1955                 u8 our_max = SER_FMT_VER_HIGHEST;
1956                 // Use the highest version supported by both
1957                 u8 deployed = core::min_(client_max, our_max);
1958                 // If it's lower than the lowest supported, give up.
1959                 if(deployed < SER_FMT_VER_LOWEST)
1960                         deployed = SER_FMT_VER_INVALID;
1961
1962                 //peer->serialization_version = deployed;
1963                 getClient(peer_id)->pending_serialization_version = deployed;
1964                 
1965                 if(deployed == SER_FMT_VER_INVALID)
1966                 {
1967                         actionstream<<"Server: A mismatched client tried to connect from "
1968                                         <<addr_s<<std::endl;
1969                         infostream<<"Server: Cannot negotiate "
1970                                         "serialization version with peer "
1971                                         <<peer_id<<std::endl;
1972                         SendAccessDenied(m_con, peer_id, std::wstring(
1973                                         L"Your client's version is not supported.\n"
1974                                         L"Server version is ")
1975                                         + narrow_to_wide(VERSION_STRING) + L"."
1976                         );
1977                         return;
1978                 }
1979                 
1980                 /*
1981                         Read and check network protocol version
1982                 */
1983
1984                 u16 net_proto_version = 0;
1985                 if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2)
1986                 {
1987                         net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
1988                 }
1989
1990                 getClient(peer_id)->net_proto_version = net_proto_version;
1991
1992                 if(net_proto_version == 0)
1993                 {
1994                         actionstream<<"Server: An old tried to connect from "<<addr_s
1995                                         <<std::endl;
1996                         SendAccessDenied(m_con, peer_id, std::wstring(
1997                                         L"Your client's version is not supported.\n"
1998                                         L"Server version is ")
1999                                         + narrow_to_wide(VERSION_STRING) + L"."
2000                         );
2001                         return;
2002                 }
2003                 
2004                 if(g_settings->getBool("strict_protocol_version_checking"))
2005                 {
2006                         if(net_proto_version != PROTOCOL_VERSION)
2007                         {
2008                                 actionstream<<"Server: A mismatched client tried to connect"
2009                                                 <<" from "<<addr_s<<std::endl;
2010                                 SendAccessDenied(m_con, peer_id, std::wstring(
2011                                                 L"Your client's version is not supported.\n"
2012                                                 L"Server version is ")
2013                                                 + narrow_to_wide(VERSION_STRING) + L",\n"
2014                                                 + L"server's PROTOCOL_VERSION is "
2015                                                 + narrow_to_wide(itos(PROTOCOL_VERSION))
2016                                                 + L", client's PROTOCOL_VERSION is "
2017                                                 + narrow_to_wide(itos(net_proto_version))
2018                                 );
2019                                 return;
2020                         }
2021                 }
2022
2023                 /*
2024                         Set up player
2025                 */
2026                 
2027                 // Get player name
2028                 char playername[PLAYERNAME_SIZE];
2029                 for(u32 i=0; i<PLAYERNAME_SIZE-1; i++)
2030                 {
2031                         playername[i] = data[3+i];
2032                 }
2033                 playername[PLAYERNAME_SIZE-1] = 0;
2034                 
2035                 if(playername[0]=='\0')
2036                 {
2037                         actionstream<<"Server: Player with an empty name "
2038                                         <<"tried to connect from "<<addr_s<<std::endl;
2039                         SendAccessDenied(m_con, peer_id,
2040                                         L"Empty name");
2041                         return;
2042                 }
2043
2044                 if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false)
2045                 {
2046                         actionstream<<"Server: Player with an invalid name "
2047                                         <<"tried to connect from "<<addr_s<<std::endl;
2048                         SendAccessDenied(m_con, peer_id,
2049                                         L"Name contains unallowed characters");
2050                         return;
2051                 }
2052
2053                 infostream<<"Server: New connection: \""<<playername<<"\" from "
2054                                 <<m_con.GetPeerAddress(peer_id).serializeString()<<std::endl;
2055
2056                 // Get password
2057                 char password[PASSWORD_SIZE];
2058                 if(datasize < 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE)
2059                 {
2060                         // old version - assume blank password
2061                         password[0] = 0;
2062                 }
2063                 else
2064                 {
2065                         for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2066                         {
2067                                 password[i] = data[23+i];
2068                         }
2069                         password[PASSWORD_SIZE-1] = 0;
2070                 }
2071                 
2072                 // Add player to auth manager
2073                 if(m_authmanager.exists(playername) == false)
2074                 {
2075                         std::wstring default_password =
2076                                 narrow_to_wide(g_settings->get("default_password"));
2077                         std::string translated_default_password =
2078                                 translatePassword(playername, default_password);
2079
2080                         // If default_password is empty, allow any initial password
2081                         if (default_password.length() == 0)
2082                                 translated_default_password = password;
2083
2084                         infostream<<"Server: adding player "<<playername
2085                                         <<" to auth manager"<<std::endl;
2086                         m_authmanager.add(playername);
2087                         m_authmanager.setPassword(playername, translated_default_password);
2088                         m_authmanager.setPrivs(playername,
2089                                         stringToPrivs(g_settings->get("default_privs")));
2090                         m_authmanager.save();
2091                 }
2092
2093                 std::string checkpwd = m_authmanager.getPassword(playername);
2094
2095                 /*infostream<<"Server: Client gave password '"<<password
2096                                 <<"', the correct one is '"<<checkpwd<<"'"<<std::endl;*/
2097
2098                 if(password != checkpwd)
2099                 {
2100                         infostream<<"Server: peer_id="<<peer_id
2101                                         <<": supplied invalid password for "
2102                                         <<playername<<std::endl;
2103                         SendAccessDenied(m_con, peer_id, L"Invalid password");
2104                         return;
2105                 }
2106
2107                 // Do not allow multiple players in simple singleplayer mode.
2108                 // This isn't a perfect way to do it, but will suffice for now.
2109                 if(m_simple_singleplayer_mode && m_clients.size() > 1){
2110                         infostream<<"Server: Not allowing another client to connect in"
2111                                         <<" simple singleplayer mode"<<std::endl;
2112                         SendAccessDenied(m_con, peer_id,
2113                                         L"Running in simple singleplayer mode.");
2114                         return;
2115                 }
2116                 
2117                 // Enforce user limit.
2118                 // Don't enforce for users that have some admin right
2119                 if(m_clients.size() >= g_settings->getU16("max_users") &&
2120                                 (m_authmanager.getPrivs(playername)
2121                                         & (PRIV_SERVER|PRIV_BAN|PRIV_PRIVS|PRIV_PASSWORD)) == 0 &&
2122                                 playername != g_settings->get("name"))
2123                 {
2124                         actionstream<<"Server: "<<playername<<" tried to join, but there"
2125                                         <<" are already max_users="
2126                                         <<g_settings->getU16("max_users")<<" players."<<std::endl;
2127                         SendAccessDenied(m_con, peer_id, L"Too many users.");
2128                         return;
2129                 }
2130
2131                 // Get player
2132                 ServerRemotePlayer *player = emergePlayer(playername, peer_id);
2133
2134                 // If failed, cancel
2135                 if(player == NULL)
2136                 {
2137                         errorstream<<"Server: peer_id="<<peer_id
2138                                         <<": failed to emerge player"<<std::endl;
2139                         return;
2140                 }
2141
2142                 /*
2143                         Answer with a TOCLIENT_INIT
2144                 */
2145                 {
2146                         SharedBuffer<u8> reply(2+1+6+8);
2147                         writeU16(&reply[0], TOCLIENT_INIT);
2148                         writeU8(&reply[2], deployed);
2149                         writeV3S16(&reply[2+1], floatToInt(player->getPosition()+v3f(0,BS/2,0), BS));
2150                         writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
2151                         
2152                         // Send as reliable
2153                         m_con.Send(peer_id, 0, reply, true);
2154                 }
2155
2156                 /*
2157                         Send complete position information
2158                 */
2159                 SendMovePlayer(player);
2160
2161                 return;
2162         }
2163
2164         if(command == TOSERVER_INIT2)
2165         {
2166                 verbosestream<<"Server: Got TOSERVER_INIT2 from "
2167                                 <<peer_id<<std::endl;
2168
2169
2170                 getClient(peer_id)->serialization_version
2171                                 = getClient(peer_id)->pending_serialization_version;
2172
2173                 /*
2174                         Send some initialization data
2175                 */
2176
2177                 infostream<<"Server: Sending content to "
2178                                 <<getPlayerName(peer_id)<<std::endl;
2179
2180                 // Send item definitions
2181                 SendItemDef(m_con, peer_id, m_itemdef);
2182                 
2183                 // Send node definitions
2184                 SendNodeDef(m_con, peer_id, m_nodedef);
2185                 
2186                 // Send texture announcement
2187                 sendMediaAnnouncement(peer_id);
2188                 
2189                 // Send player info to all players
2190                 //SendPlayerInfos();
2191
2192                 // Send inventory to player
2193                 UpdateCrafting(peer_id);
2194                 SendInventory(peer_id);
2195                 
2196                 // Send player items to all players
2197                 SendPlayerItems();
2198
2199                 Player *player = m_env->getPlayer(peer_id);
2200
2201                 // Send HP
2202                 SendPlayerHP(player);
2203                 
2204                 // Show death screen if necessary
2205                 if(player->hp == 0)
2206                         SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
2207
2208                 // Send time of day
2209                 {
2210                         SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
2211                                         m_env->getTimeOfDay(), g_settings->getFloat("time_speed"));
2212                         m_con.Send(peer_id, 0, data, true);
2213                 }
2214                 
2215                 // Note things in chat if not in simple singleplayer mode
2216                 if(!m_simple_singleplayer_mode)
2217                 {
2218                         // Send information about server to player in chat
2219                         SendChatMessage(peer_id, getStatusString());
2220                         
2221                         // Send information about joining in chat
2222                         {
2223                                 std::wstring name = L"unknown";
2224                                 Player *player = m_env->getPlayer(peer_id);
2225                                 if(player != NULL)
2226                                         name = narrow_to_wide(player->getName());
2227                                 
2228                                 std::wstring message;
2229                                 message += L"*** ";
2230                                 message += name;
2231                                 message += L" joined game";
2232                                 BroadcastChatMessage(message);
2233                         }
2234                 }
2235                 
2236                 // Warnings about protocol version can be issued here
2237                 if(getClient(peer_id)->net_proto_version < PROTOCOL_VERSION)
2238                 {
2239                         SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER");
2240                 }
2241
2242                 /*
2243                         Print out action
2244                 */
2245                 {
2246                         std::ostringstream os(std::ios_base::binary);
2247                         for(core::map<u16, RemoteClient*>::Iterator
2248                                 i = m_clients.getIterator();
2249                                 i.atEnd() == false; i++)
2250                         {
2251                                 RemoteClient *client = i.getNode()->getValue();
2252                                 assert(client->peer_id == i.getNode()->getKey());
2253                                 if(client->serialization_version == SER_FMT_VER_INVALID)
2254                                         continue;
2255                                 // Get player
2256                                 Player *player = m_env->getPlayer(client->peer_id);
2257                                 if(!player)
2258                                         continue;
2259                                 // Get name of player
2260                                 os<<player->getName()<<" ";
2261                         }
2262
2263                         actionstream<<player->getName()<<" joins game. List of players: "
2264                                         <<os.str()<<std::endl;
2265                 }
2266
2267                 return;
2268         }
2269
2270         if(peer_ser_ver == SER_FMT_VER_INVALID)
2271         {
2272                 infostream<<"Server::ProcessData(): Cancelling: Peer"
2273                                 " serialization format invalid or not initialized."
2274                                 " Skipping incoming command="<<command<<std::endl;
2275                 return;
2276         }
2277         
2278         Player *player = m_env->getPlayer(peer_id);
2279         ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
2280
2281         if(player == NULL){
2282                 infostream<<"Server::ProcessData(): Cancelling: "
2283                                 "No player for peer_id="<<peer_id
2284                                 <<std::endl;
2285                 return;
2286         }
2287         if(command == TOSERVER_PLAYERPOS)
2288         {
2289                 if(datasize < 2+12+12+4+4)
2290                         return;
2291         
2292                 u32 start = 0;
2293                 v3s32 ps = readV3S32(&data[start+2]);
2294                 v3s32 ss = readV3S32(&data[start+2+12]);
2295                 f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0;
2296                 f32 yaw = (f32)readS32(&data[2+12+12+4]) / 100.0;
2297                 v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.);
2298                 v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.);
2299                 pitch = wrapDegrees(pitch);
2300                 yaw = wrapDegrees(yaw);
2301
2302                 player->setPosition(position);
2303                 player->setSpeed(speed);
2304                 player->setPitch(pitch);
2305                 player->setYaw(yaw);
2306                 
2307                 /*infostream<<"Server::ProcessData(): Moved player "<<peer_id<<" to "
2308                                 <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
2309                                 <<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
2310         }
2311         else if(command == TOSERVER_GOTBLOCKS)
2312         {
2313                 if(datasize < 2+1)
2314                         return;
2315                 
2316                 /*
2317                         [0] u16 command
2318                         [2] u8 count
2319                         [3] v3s16 pos_0
2320                         [3+6] v3s16 pos_1
2321                         ...
2322                 */
2323
2324                 u16 count = data[2];
2325                 for(u16 i=0; i<count; i++)
2326                 {
2327                         if((s16)datasize < 2+1+(i+1)*6)
2328                                 throw con::InvalidIncomingDataException
2329                                         ("GOTBLOCKS length is too short");
2330                         v3s16 p = readV3S16(&data[2+1+i*6]);
2331                         /*infostream<<"Server: GOTBLOCKS ("
2332                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
2333                         RemoteClient *client = getClient(peer_id);
2334                         client->GotBlock(p);
2335                 }
2336         }
2337         else if(command == TOSERVER_DELETEDBLOCKS)
2338         {
2339                 if(datasize < 2+1)
2340                         return;
2341                 
2342                 /*
2343                         [0] u16 command
2344                         [2] u8 count
2345                         [3] v3s16 pos_0
2346                         [3+6] v3s16 pos_1
2347                         ...
2348                 */
2349
2350                 u16 count = data[2];
2351                 for(u16 i=0; i<count; i++)
2352                 {
2353                         if((s16)datasize < 2+1+(i+1)*6)
2354                                 throw con::InvalidIncomingDataException
2355                                         ("DELETEDBLOCKS length is too short");
2356                         v3s16 p = readV3S16(&data[2+1+i*6]);
2357                         /*infostream<<"Server: DELETEDBLOCKS ("
2358                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
2359                         RemoteClient *client = getClient(peer_id);
2360                         client->SetBlockNotSent(p);
2361                 }
2362         }
2363         else if(command == TOSERVER_CLICK_OBJECT)
2364         {
2365                 infostream<<"Server: CLICK_OBJECT not supported anymore"<<std::endl;
2366                 return;
2367         }
2368         else if(command == TOSERVER_CLICK_ACTIVEOBJECT)
2369         {
2370                 infostream<<"Server: CLICK_ACTIVEOBJECT not supported anymore"<<std::endl;
2371                 return;
2372         }
2373         else if(command == TOSERVER_GROUND_ACTION)
2374         {
2375                 infostream<<"Server: GROUND_ACTION not supported anymore"<<std::endl;
2376                 return;
2377
2378         }
2379         else if(command == TOSERVER_RELEASE)
2380         {
2381                 infostream<<"Server: RELEASE not supported anymore"<<std::endl;
2382                 return;
2383         }
2384         else if(command == TOSERVER_SIGNTEXT)
2385         {
2386                 infostream<<"Server: SIGNTEXT not supported anymore"
2387                                 <<std::endl;
2388                 return;
2389         }
2390         else if(command == TOSERVER_SIGNNODETEXT)
2391         {
2392                 if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
2393                         return;
2394                 /*
2395                         u16 command
2396                         v3s16 p
2397                         u16 textlen
2398                         textdata
2399                 */
2400                 std::string datastring((char*)&data[2], datasize-2);
2401                 std::istringstream is(datastring, std::ios_base::binary);
2402                 u8 buf[6];
2403                 // Read stuff
2404                 is.read((char*)buf, 6);
2405                 v3s16 p = readV3S16(buf);
2406                 is.read((char*)buf, 2);
2407                 u16 textlen = readU16(buf);
2408                 std::string text;
2409                 for(u16 i=0; i<textlen; i++)
2410                 {
2411                         is.read((char*)buf, 1);
2412                         text += (char)buf[0];
2413                 }
2414
2415                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
2416                 if(!meta)
2417                         return;
2418
2419                 meta->setText(text);
2420                 
2421                 actionstream<<player->getName()<<" writes \""<<text<<"\" to sign"
2422                                 <<" at "<<PP(p)<<std::endl;
2423                                 
2424                 v3s16 blockpos = getNodeBlockPos(p);
2425                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
2426                 if(block)
2427                 {
2428                         block->raiseModified(MOD_STATE_WRITE_NEEDED,
2429                                         "sign node text");
2430                 }
2431
2432                 setBlockNotSent(blockpos);
2433         }
2434         else if(command == TOSERVER_INVENTORY_ACTION)
2435         {
2436                 // Strip command and create a stream
2437                 std::string datastring((char*)&data[2], datasize-2);
2438                 verbosestream<<"TOSERVER_INVENTORY_ACTION: data="<<datastring<<std::endl;
2439                 std::istringstream is(datastring, std::ios_base::binary);
2440                 // Create an action
2441                 InventoryAction *a = InventoryAction::deSerialize(is);
2442                 if(a == NULL)
2443                 {
2444                         infostream<<"TOSERVER_INVENTORY_ACTION: "
2445                                         <<"InventoryAction::deSerialize() returned NULL"
2446                                         <<std::endl;
2447                         return;
2448                 }
2449
2450                 /*
2451                         Note: Always set inventory not sent, to repair cases
2452                         where the client made a bad prediction.
2453                 */
2454
2455                 /*
2456                         Handle restrictions and special cases of the move action
2457                 */
2458                 if(a->getType() == IACTION_MOVE)
2459                 {
2460                         IMoveAction *ma = (IMoveAction*)a;
2461
2462                         ma->from_inv.applyCurrentPlayer(player->getName());
2463                         ma->to_inv.applyCurrentPlayer(player->getName());
2464
2465                         setInventoryModified(ma->from_inv);
2466                         setInventoryModified(ma->to_inv);
2467
2468                         bool from_inv_is_current_player =
2469                                 (ma->from_inv.type == InventoryLocation::PLAYER) &&
2470                                 (ma->from_inv.name == player->getName());
2471
2472                         bool to_inv_is_current_player =
2473                                 (ma->to_inv.type == InventoryLocation::PLAYER) &&
2474                                 (ma->to_inv.name == player->getName());
2475
2476                         /*
2477                                 Disable moving items out of craftpreview
2478                         */
2479                         if(ma->from_list == "craftpreview")
2480                         {
2481                                 infostream<<"Ignoring IMoveAction from "
2482                                                 <<(ma->from_inv.dump())<<":"<<ma->from_list
2483                                                 <<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
2484                                                 <<" because src is "<<ma->from_list<<std::endl;
2485                                 delete a;
2486                                 return;
2487                         }
2488
2489                         /*
2490                                 Disable moving items into craftresult and craftpreview
2491                         */
2492                         if(ma->to_list == "craftpreview" || ma->to_list == "craftresult")
2493                         {
2494                                 infostream<<"Ignoring IMoveAction from "
2495                                                 <<(ma->from_inv.dump())<<":"<<ma->from_list
2496                                                 <<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
2497                                                 <<" because dst is "<<ma->to_list<<std::endl;
2498                                 delete a;
2499                                 return;
2500                         }
2501
2502                         // Disallow moving items in elsewhere than player's inventory
2503                         // if not allowed to interact
2504                         if((getPlayerPrivs(player) & PRIV_INTERACT) == 0
2505                                         && (!from_inv_is_current_player
2506                                         || !to_inv_is_current_player))
2507                         {
2508                                 infostream<<"Cannot move outside of player's inventory: "
2509                                                 <<"No interact privilege"<<std::endl;
2510                                 delete a;
2511                                 return;
2512                         }
2513
2514                         // If player is not an admin, check for ownership of src and dst
2515                         if((getPlayerPrivs(player) & PRIV_SERVER) == 0)
2516                         {
2517                                 std::string owner_from = getInventoryOwner(ma->from_inv);
2518                                 if(owner_from != "" && owner_from != player->getName())
2519                                 {
2520                                         infostream<<"WARNING: "<<player->getName()
2521                                                 <<" tried to access an inventory that"
2522                                                 <<" belongs to "<<owner_from<<std::endl;
2523                                         delete a;
2524                                         return;
2525                                 }
2526
2527                                 std::string owner_to = getInventoryOwner(ma->to_inv);
2528                                 if(owner_to != "" && owner_to != player->getName())
2529                                 {
2530                                         infostream<<"WARNING: "<<player->getName()
2531                                                 <<" tried to access an inventory that"
2532                                                 <<" belongs to "<<owner_to<<std::endl;
2533                                         delete a;
2534                                         return;
2535                                 }
2536                         }
2537                 }
2538                 /*
2539                         Handle restrictions and special cases of the drop action
2540                 */
2541                 else if(a->getType() == IACTION_DROP)
2542                 {
2543                         IDropAction *da = (IDropAction*)a;
2544
2545                         da->from_inv.applyCurrentPlayer(player->getName());
2546
2547                         setInventoryModified(da->from_inv);
2548
2549                         // Disallow dropping items if not allowed to interact
2550                         if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
2551                         {
2552                                 delete a;
2553                                 return;
2554                         }
2555                         // If player is not an admin, check for ownership
2556                         else if((getPlayerPrivs(player) & PRIV_SERVER) == 0)
2557                         {
2558                                 std::string owner_from = getInventoryOwner(da->from_inv);
2559                                 if(owner_from != "" && owner_from != player->getName())
2560                                 {
2561                                         infostream<<"WARNING: "<<player->getName()
2562                                                 <<" tried to access an inventory that"
2563                                                 <<" belongs to "<<owner_from<<std::endl;
2564                                         delete a;
2565                                         return;
2566                                 }
2567                         }
2568                 }
2569                 /*
2570                         Handle restrictions and special cases of the craft action
2571                 */
2572                 else if(a->getType() == IACTION_CRAFT)
2573                 {
2574                         ICraftAction *ca = (ICraftAction*)a;
2575
2576                         ca->craft_inv.applyCurrentPlayer(player->getName());
2577
2578                         setInventoryModified(ca->craft_inv);
2579
2580                         //bool craft_inv_is_current_player =
2581                         //      (ca->craft_inv.type == InventoryLocation::PLAYER) &&
2582                         //      (ca->craft_inv.name == player->getName());
2583
2584                         // Disallow crafting if not allowed to interact
2585                         if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
2586                         {
2587                                 infostream<<"Cannot craft: "
2588                                                 <<"No interact privilege"<<std::endl;
2589                                 delete a;
2590                                 return;
2591                         }
2592
2593                         // If player is not an admin, check for ownership of inventory
2594                         if((getPlayerPrivs(player) & PRIV_SERVER) == 0)
2595                         {
2596                                 std::string owner_craft = getInventoryOwner(ca->craft_inv);
2597                                 if(owner_craft != "" && owner_craft != player->getName())
2598                                 {
2599                                         infostream<<"WARNING: "<<player->getName()
2600                                                 <<" tried to access an inventory that"
2601                                                 <<" belongs to "<<owner_craft<<std::endl;
2602                                         delete a;
2603                                         return;
2604                                 }
2605                         }
2606                 }
2607                 
2608                 // Do the action
2609                 a->apply(this, srp, this);
2610                 // Eat the action
2611                 delete a;
2612         }
2613         else if(command == TOSERVER_CHAT_MESSAGE)
2614         {
2615                 /*
2616                         u16 command
2617                         u16 length
2618                         wstring message
2619                 */
2620                 u8 buf[6];
2621                 std::string datastring((char*)&data[2], datasize-2);
2622                 std::istringstream is(datastring, std::ios_base::binary);
2623                 
2624                 // Read stuff
2625                 is.read((char*)buf, 2);
2626                 u16 len = readU16(buf);
2627                 
2628                 std::wstring message;
2629                 for(u16 i=0; i<len; i++)
2630                 {
2631                         is.read((char*)buf, 2);
2632                         message += (wchar_t)readU16(buf);
2633                 }
2634
2635                 // Get player name of this client
2636                 std::wstring name = narrow_to_wide(player->getName());
2637                 
2638                 // Run script hook
2639                 bool ate = scriptapi_on_chat_message(m_lua, player->getName(),
2640                                 wide_to_narrow(message));
2641                 // If script ate the message, don't proceed
2642                 if(ate)
2643                         return;
2644                 
2645                 // Line to send to players
2646                 std::wstring line;
2647                 // Whether to send to the player that sent the line
2648                 bool send_to_sender = false;
2649                 // Whether to send to other players
2650                 bool send_to_others = false;
2651                 
2652                 // Local player gets all privileges regardless of
2653                 // what's set on their account.
2654                 u64 privs = getPlayerPrivs(player);
2655
2656                 // Parse commands
2657                 if(message[0] == L'/')
2658                 {
2659                         size_t strip_size = 1;
2660                         if (message[1] == L'#') // support old-style commans
2661                                 ++strip_size;
2662                         message = message.substr(strip_size);
2663
2664                         WStrfnd f1(message);
2665                         f1.next(L" "); // Skip over /#whatever
2666                         std::wstring paramstring = f1.next(L"");
2667
2668                         ServerCommandContext *ctx = new ServerCommandContext(
2669                                 str_split(message, L' '),
2670                                 paramstring,
2671                                 this,
2672                                 m_env,
2673                                 player,
2674                                 privs);
2675
2676                         std::wstring reply(processServerCommand(ctx));
2677                         send_to_sender = ctx->flags & SEND_TO_SENDER;
2678                         send_to_others = ctx->flags & SEND_TO_OTHERS;
2679
2680                         if (ctx->flags & SEND_NO_PREFIX)
2681                                 line += reply;
2682                         else
2683                                 line += L"Server: " + reply;
2684
2685                         delete ctx;
2686
2687                 }
2688                 else
2689                 {
2690                         if(privs & PRIV_SHOUT)
2691                         {
2692                                 line += L"<";
2693                                 line += name;
2694                                 line += L"> ";
2695                                 line += message;
2696                                 send_to_others = true;
2697                         }
2698                         else
2699                         {
2700                                 line += L"Server: You are not allowed to shout";
2701                                 send_to_sender = true;
2702                         }
2703                 }
2704                 
2705                 if(line != L"")
2706                 {
2707                         if(send_to_others)
2708                                 actionstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
2709
2710                         /*
2711                                 Send the message to clients
2712                         */
2713                         for(core::map<u16, RemoteClient*>::Iterator
2714                                 i = m_clients.getIterator();
2715                                 i.atEnd() == false; i++)
2716                         {
2717                                 // Get client and check that it is valid
2718                                 RemoteClient *client = i.getNode()->getValue();
2719                                 assert(client->peer_id == i.getNode()->getKey());
2720                                 if(client->serialization_version == SER_FMT_VER_INVALID)
2721                                         continue;
2722
2723                                 // Filter recipient
2724                                 bool sender_selected = (peer_id == client->peer_id);
2725                                 if(sender_selected == true && send_to_sender == false)
2726                                         continue;
2727                                 if(sender_selected == false && send_to_others == false)
2728                                         continue;
2729
2730                                 SendChatMessage(client->peer_id, line);
2731                         }
2732                 }
2733         }
2734         else if(command == TOSERVER_DAMAGE)
2735         {
2736                 std::string datastring((char*)&data[2], datasize-2);
2737                 std::istringstream is(datastring, std::ios_base::binary);
2738                 u8 damage = readU8(is);
2739
2740                 ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
2741
2742                 if(g_settings->getBool("enable_damage"))
2743                 {
2744                         actionstream<<player->getName()<<" damaged by "
2745                                         <<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
2746                                         <<std::endl;
2747
2748                         srp->setHP(srp->getHP() - damage);
2749
2750                         if(srp->getHP() == 0 && srp->m_hp_not_sent)
2751                                 DiePlayer(srp);
2752
2753                         if(srp->m_hp_not_sent)
2754                                 SendPlayerHP(player);
2755                 }
2756                 else
2757                 {
2758                         // Force send (to correct the client's predicted HP)
2759                         SendPlayerHP(player);
2760                 }
2761         }
2762         else if(command == TOSERVER_PASSWORD)
2763         {
2764                 /*
2765                         [0] u16 TOSERVER_PASSWORD
2766                         [2] u8[28] old password
2767                         [30] u8[28] new password
2768                 */
2769
2770                 if(datasize != 2+PASSWORD_SIZE*2)
2771                         return;
2772                 /*char password[PASSWORD_SIZE];
2773                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2774                         password[i] = data[2+i];
2775                 password[PASSWORD_SIZE-1] = 0;*/
2776                 std::string oldpwd;
2777                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2778                 {
2779                         char c = data[2+i];
2780                         if(c == 0)
2781                                 break;
2782                         oldpwd += c;
2783                 }
2784                 std::string newpwd;
2785                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2786                 {
2787                         char c = data[2+PASSWORD_SIZE+i];
2788                         if(c == 0)
2789                                 break;
2790                         newpwd += c;
2791                 }
2792
2793                 infostream<<"Server: Client requests a password change from "
2794                                 <<"'"<<oldpwd<<"' to '"<<newpwd<<"'"<<std::endl;
2795
2796                 std::string playername = player->getName();
2797
2798                 if(m_authmanager.exists(playername) == false)
2799                 {
2800                         infostream<<"Server: playername not found in authmanager"<<std::endl;
2801                         // Wrong old password supplied!!
2802                         SendChatMessage(peer_id, L"playername not found in authmanager");
2803                         return;
2804                 }
2805
2806                 std::string checkpwd = m_authmanager.getPassword(playername);
2807
2808                 if(oldpwd != checkpwd)
2809                 {
2810                         infostream<<"Server: invalid old password"<<std::endl;
2811                         // Wrong old password supplied!!
2812                         SendChatMessage(peer_id, L"Invalid old password supplied. Password NOT changed.");
2813                         return;
2814                 }
2815
2816                 actionstream<<player->getName()<<" changes password"<<std::endl;
2817
2818                 m_authmanager.setPassword(playername, newpwd);
2819                 
2820                 infostream<<"Server: password change successful for "<<playername
2821                                 <<std::endl;
2822                 SendChatMessage(peer_id, L"Password change successful");
2823         }
2824         else if(command == TOSERVER_PLAYERITEM)
2825         {
2826                 if (datasize < 2+2)
2827                         return;
2828
2829                 u16 item = readU16(&data[2]);
2830                 srp->setWieldIndex(item);
2831                 SendWieldedItem(srp);
2832         }
2833         else if(command == TOSERVER_RESPAWN)
2834         {
2835                 if(player->hp != 0)
2836                         return;
2837                 
2838                 RespawnPlayer(player);
2839                 
2840                 actionstream<<player->getName()<<" respawns at "
2841                                 <<PP(player->getPosition()/BS)<<std::endl;
2842
2843                 // ActiveObject is added to environment in AsyncRunStep after
2844                 // the previous addition has been succesfully removed
2845         }
2846         else if(command == TOSERVER_REQUEST_MEDIA) {
2847                 std::string datastring((char*)&data[2], datasize-2);
2848                 std::istringstream is(datastring, std::ios_base::binary);
2849                 
2850                 core::list<MediaRequest> tosend;
2851                 u16 numfiles = readU16(is);
2852
2853                 infostream<<"Sending "<<numfiles<<" files to "
2854                                 <<getPlayerName(peer_id)<<std::endl;
2855                 verbosestream<<"TOSERVER_REQUEST_MEDIA: "<<std::endl;
2856
2857                 for(int i = 0; i < numfiles; i++) {
2858                         std::string name = deSerializeString(is);
2859                         tosend.push_back(MediaRequest(name));
2860                         verbosestream<<"TOSERVER_REQUEST_MEDIA: requested file "
2861                                         <<name<<std::endl;
2862                 }
2863
2864                 sendRequestedMedia(peer_id, tosend);
2865
2866                 // Now the client should know about everything
2867                 // (definitions and files)
2868                 getClient(peer_id)->definitions_sent = true;
2869         }
2870         else if(command == TOSERVER_INTERACT)
2871         {
2872                 std::string datastring((char*)&data[2], datasize-2);
2873                 std::istringstream is(datastring, std::ios_base::binary);
2874
2875                 /*
2876                         [0] u16 command
2877                         [2] u8 action
2878                         [3] u16 item
2879                         [5] u32 length of the next item
2880                         [9] serialized PointedThing
2881                         actions:
2882                         0: start digging (from undersurface) or use
2883                         1: stop digging (all parameters ignored)
2884                         2: digging completed
2885                         3: place block or item (to abovesurface)
2886                         4: use item
2887                 */
2888                 u8 action = readU8(is);
2889                 u16 item_i = readU16(is);
2890                 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
2891                 PointedThing pointed;
2892                 pointed.deSerialize(tmp_is);
2893
2894                 verbosestream<<"TOSERVER_INTERACT: action="<<(int)action<<", item="
2895                                 <<item_i<<", pointed="<<pointed.dump()<<std::endl;
2896
2897                 if(player->hp == 0)
2898                 {
2899                         verbosestream<<"TOSERVER_INTERACT: "<<srp->getName()
2900                                 <<" tried to interact, but is dead!"<<std::endl;
2901                         return;
2902                 }
2903
2904                 v3f player_pos = srp->m_last_good_position;
2905
2906                 // Update wielded item
2907                 if(srp->getWieldIndex() != item_i)
2908                 {
2909                         srp->setWieldIndex(item_i);
2910                         SendWieldedItem(srp);
2911                 }
2912
2913                 // Get pointed to node (undefined if not POINTEDTYPE_NODE)
2914                 v3s16 p_under = pointed.node_undersurface;
2915                 v3s16 p_above = pointed.node_abovesurface;
2916
2917                 // Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
2918                 ServerActiveObject *pointed_object = NULL;
2919                 if(pointed.type == POINTEDTHING_OBJECT)
2920                 {
2921                         pointed_object = m_env->getActiveObject(pointed.object_id);
2922                         if(pointed_object == NULL)
2923                         {
2924                                 verbosestream<<"TOSERVER_INTERACT: "
2925                                         "pointed object is NULL"<<std::endl;
2926                                 return;
2927                         }
2928
2929                 }
2930
2931                 v3f pointed_pos_under = player_pos;
2932                 v3f pointed_pos_above = player_pos;
2933                 if(pointed.type == POINTEDTHING_NODE)
2934                 {
2935                         pointed_pos_under = intToFloat(p_under, BS);
2936                         pointed_pos_above = intToFloat(p_above, BS);
2937                 }
2938                 else if(pointed.type == POINTEDTHING_OBJECT)
2939                 {
2940                         pointed_pos_under = pointed_object->getBasePosition();
2941                         pointed_pos_above = pointed_pos_under;
2942                 }
2943
2944                 /*
2945                         Check that target is reasonably close
2946                         (only when digging or placing things)
2947                 */
2948                 if(action == 0 || action == 2 || action == 3)
2949                 {
2950                         float d = player_pos.getDistanceFrom(pointed_pos_under);
2951                         float max_d = BS * 14; // Just some large enough value
2952                         if(d > max_d){
2953                                 actionstream<<"Player "<<player->getName()
2954                                                 <<" tried to access "<<pointed.dump()
2955                                                 <<" from too far: "
2956                                                 <<"d="<<d<<", max_d="<<max_d
2957                                                 <<". ignoring."<<std::endl;
2958                                 // Re-send block to revert change on client-side
2959                                 RemoteClient *client = getClient(peer_id);
2960                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2961                                 client->SetBlockNotSent(blockpos);
2962                                 // Do nothing else
2963                                 return;
2964                         }
2965                 }
2966
2967                 /*
2968                         Make sure the player is allowed to do it
2969                 */
2970                 if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
2971                 {
2972                         infostream<<"Ignoring interaction from player "<<player->getName()
2973                                         <<" because privileges are "<<getPlayerPrivs(player)
2974                                         <<std::endl;
2975                         return;
2976                 }
2977
2978                 /*
2979                         0: start digging or punch object
2980                 */
2981                 if(action == 0)
2982                 {
2983                         if(pointed.type == POINTEDTHING_NODE)
2984                         {
2985                                 /*
2986                                         NOTE: This can be used in the future to check if
2987                                         somebody is cheating, by checking the timing.
2988                                 */
2989                                 MapNode n(CONTENT_IGNORE);
2990                                 try
2991                                 {
2992                                         n = m_env->getMap().getNode(p_under);
2993                                 }
2994                                 catch(InvalidPositionException &e)
2995                                 {
2996                                         infostream<<"Server: Not punching: Node not found."
2997                                                         <<" Adding block to emerge queue."
2998                                                         <<std::endl;
2999                                         m_emerge_queue.addBlock(peer_id,
3000                                                         getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
3001                                 }
3002                                 if(n.getContent() != CONTENT_IGNORE)
3003                                         scriptapi_node_on_punch(m_lua, p_under, n, srp);
3004                         }
3005                         else if(pointed.type == POINTEDTHING_OBJECT)
3006                         {
3007                                 // Skip if object has been removed
3008                                 if(pointed_object->m_removed)
3009                                         return;
3010
3011                                 actionstream<<player->getName()<<" punches object "
3012                                                 <<pointed.object_id<<": "
3013                                                 <<pointed_object->getDescription()<<std::endl;
3014
3015                                 ItemStack punchitem = srp->getWieldedItem();
3016                                 ToolCapabilities toolcap =
3017                                                 punchitem.getToolCapabilities(m_itemdef);
3018                                 v3f dir = (pointed_object->getBasePosition() -
3019                                                 (srp->getPosition() + srp->getEyeOffset())
3020                                                         ).normalize();
3021                                 pointed_object->punch(dir, &toolcap, srp,
3022                                                 srp->m_time_from_last_punch);
3023                                 srp->m_time_from_last_punch = 0;
3024                         }
3025
3026                 } // action == 0
3027
3028                 /*
3029                         1: stop digging
3030                 */
3031                 else if(action == 1)
3032                 {
3033                 } // action == 1
3034
3035                 /*
3036                         2: Digging completed
3037                 */
3038                 else if(action == 2)
3039                 {
3040                         // Only complete digging of nodes
3041                         if(pointed.type == POINTEDTHING_NODE)
3042                         {
3043                                 MapNode n(CONTENT_IGNORE);
3044                                 try
3045                                 {
3046                                         n = m_env->getMap().getNode(p_under);
3047                                 }
3048                                 catch(InvalidPositionException &e)
3049                                 {
3050                                         infostream<<"Server: Not finishing digging: Node not found."
3051                                                         <<" Adding block to emerge queue."
3052                                                         <<std::endl;
3053                                         m_emerge_queue.addBlock(peer_id,
3054                                                         getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
3055                                 }
3056                                 if(n.getContent() != CONTENT_IGNORE)
3057                                         scriptapi_node_on_dig(m_lua, p_under, n, srp);
3058                         }
3059                 } // action == 2
3060                 
3061                 /*
3062                         3: place block or right-click object
3063                 */
3064                 else if(action == 3)
3065                 {
3066                         ItemStack item = srp->getWieldedItem();
3067
3068                         // Reset build time counter
3069                         if(pointed.type == POINTEDTHING_NODE &&
3070                                         item.getDefinition(m_itemdef).type == ITEM_NODE)
3071                                 getClient(peer_id)->m_time_from_building = 0.0;
3072
3073                         if(pointed.type == POINTEDTHING_OBJECT)
3074                         {
3075                                 // Right click object
3076
3077                                 // Skip if object has been removed
3078                                 if(pointed_object->m_removed)
3079                                         return;
3080
3081                                 actionstream<<player->getName()<<" right-clicks object "
3082                                                 <<pointed.object_id<<": "
3083                                                 <<pointed_object->getDescription()<<std::endl;
3084
3085                                 // Do stuff
3086                                 pointed_object->rightClick(srp);
3087                         }
3088                         else if(scriptapi_item_on_place(m_lua,
3089                                         item, srp, pointed))
3090                         {
3091                                 // Placement was handled in lua
3092
3093                                 // Apply returned ItemStack
3094                                 if(g_settings->getBool("creative_mode") == false)
3095                                         srp->setWieldedItem(item);
3096                         }
3097
3098                 } // action == 3
3099
3100                 /*
3101                         4: use
3102                 */
3103                 else if(action == 4)
3104                 {
3105                         ItemStack item = srp->getWieldedItem();
3106
3107                         actionstream<<player->getName()<<" uses "<<item.name
3108                                         <<", pointing at "<<pointed.dump()<<std::endl;
3109
3110                         if(scriptapi_item_on_use(m_lua,
3111                                         item, srp, pointed))
3112                         {
3113                                 // Apply returned ItemStack
3114                                 if(g_settings->getBool("creative_mode") == false)
3115                                         srp->setWieldedItem(item);
3116                         }
3117
3118                 } // action == 4
3119
3120                 /*
3121                         Catch invalid actions
3122                 */
3123                 else
3124                 {
3125                         infostream<<"WARNING: Server: Invalid action "
3126                                         <<action<<std::endl;
3127                 }
3128         }
3129         else if(command == TOSERVER_REMOVED_SOUNDS)
3130         {
3131                 std::string datastring((char*)&data[2], datasize-2);
3132                 std::istringstream is(datastring, std::ios_base::binary);
3133
3134                 int num = readU16(is);
3135                 for(int k=0; k<num; k++){
3136                         s32 id = readS32(is);
3137                         std::map<s32, ServerPlayingSound>::iterator i =
3138                                         m_playing_sounds.find(id);
3139                         if(i == m_playing_sounds.end())
3140                                 continue;
3141                         ServerPlayingSound &psound = i->second;
3142                         psound.clients.erase(peer_id);
3143                         if(psound.clients.size() == 0)
3144                                 m_playing_sounds.erase(i++);
3145                 }
3146         }
3147         else
3148         {
3149                 infostream<<"Server::ProcessData(): Ignoring "
3150                                 "unknown command "<<command<<std::endl;
3151         }
3152         
3153         } //try
3154         catch(SendFailedException &e)
3155         {
3156                 errorstream<<"Server::ProcessData(): SendFailedException: "
3157                                 <<"what="<<e.what()
3158                                 <<std::endl;
3159         }
3160 }
3161
3162 void Server::onMapEditEvent(MapEditEvent *event)
3163 {
3164         //infostream<<"Server::onMapEditEvent()"<<std::endl;
3165         if(m_ignore_map_edit_events)
3166                 return;
3167         MapEditEvent *e = event->clone();
3168         m_unsent_map_edit_queue.push_back(e);
3169 }
3170
3171 Inventory* Server::getInventory(const InventoryLocation &loc)
3172 {
3173         switch(loc.type){
3174         case InventoryLocation::UNDEFINED:
3175         {}
3176         break;
3177         case InventoryLocation::CURRENT_PLAYER:
3178         {}
3179         break;
3180         case InventoryLocation::PLAYER:
3181         {
3182                 Player *player = m_env->getPlayer(loc.name.c_str());
3183                 if(!player)
3184                         return NULL;
3185                 return &player->inventory;
3186         }
3187         break;
3188         case InventoryLocation::NODEMETA:
3189         {
3190                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3191                 if(!meta)
3192                         return NULL;
3193                 return meta->getInventory();
3194         }
3195         break;
3196         default:
3197                 assert(0);
3198         }
3199         return NULL;
3200 }
3201 std::string Server::getInventoryOwner(const InventoryLocation &loc)
3202 {
3203         switch(loc.type){
3204         case InventoryLocation::UNDEFINED:
3205         {}
3206         break;
3207         case InventoryLocation::CURRENT_PLAYER:
3208         {}
3209         break;
3210         case InventoryLocation::PLAYER:
3211         {
3212                 return loc.name;
3213         }
3214         break;
3215         case InventoryLocation::NODEMETA:
3216         {
3217                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3218                 if(!meta)
3219                         return "";
3220                 return meta->getOwner();
3221         }
3222         break;
3223         default:
3224                 assert(0);
3225         }
3226         return "";
3227 }
3228 void Server::setInventoryModified(const InventoryLocation &loc)
3229 {
3230         switch(loc.type){
3231         case InventoryLocation::UNDEFINED:
3232         {}
3233         break;
3234         case InventoryLocation::PLAYER:
3235         {
3236                 ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>
3237                                 (m_env->getPlayer(loc.name.c_str()));
3238                 if(!srp)
3239                         return;
3240                 srp->m_inventory_not_sent = true;
3241         }
3242         break;
3243         case InventoryLocation::NODEMETA:
3244         {
3245                 v3s16 blockpos = getNodeBlockPos(loc.p);
3246
3247                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3248                 if(meta)
3249                         meta->inventoryModified();
3250                 
3251                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
3252                 if(block)
3253                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
3254                 
3255                 setBlockNotSent(blockpos);
3256         }
3257         break;
3258         default:
3259                 assert(0);
3260         }
3261 }
3262
3263 core::list<PlayerInfo> Server::getPlayerInfo()
3264 {
3265         DSTACK(__FUNCTION_NAME);
3266         JMutexAutoLock envlock(m_env_mutex);
3267         JMutexAutoLock conlock(m_con_mutex);
3268         
3269         core::list<PlayerInfo> list;
3270
3271         core::list<Player*> players = m_env->getPlayers();
3272         
3273         core::list<Player*>::Iterator i;
3274         for(i = players.begin();
3275                         i != players.end(); i++)
3276         {
3277                 PlayerInfo info;
3278
3279                 Player *player = *i;
3280
3281                 try{
3282                         // Copy info from connection to info struct
3283                         info.id = player->peer_id;
3284                         info.address = m_con.GetPeerAddress(player->peer_id);
3285                         info.avg_rtt = m_con.GetPeerAvgRTT(player->peer_id);
3286                 }
3287                 catch(con::PeerNotFoundException &e)
3288                 {
3289                         // Set dummy peer info
3290                         info.id = 0;
3291                         info.address = Address(0,0,0,0,0);
3292                         info.avg_rtt = 0.0;
3293                 }
3294
3295                 snprintf(info.name, PLAYERNAME_SIZE, "%s", player->getName());
3296                 info.position = player->getPosition();
3297
3298                 list.push_back(info);
3299         }
3300
3301         return list;
3302 }
3303
3304
3305 void Server::peerAdded(con::Peer *peer)
3306 {
3307         DSTACK(__FUNCTION_NAME);
3308         verbosestream<<"Server::peerAdded(): peer->id="
3309                         <<peer->id<<std::endl;
3310         
3311         PeerChange c;
3312         c.type = PEER_ADDED;
3313         c.peer_id = peer->id;
3314         c.timeout = false;
3315         m_peer_change_queue.push_back(c);
3316 }
3317
3318 void Server::deletingPeer(con::Peer *peer, bool timeout)
3319 {
3320         DSTACK(__FUNCTION_NAME);
3321         verbosestream<<"Server::deletingPeer(): peer->id="
3322                         <<peer->id<<", timeout="<<timeout<<std::endl;
3323         
3324         PeerChange c;
3325         c.type = PEER_REMOVED;
3326         c.peer_id = peer->id;
3327         c.timeout = timeout;
3328         m_peer_change_queue.push_back(c);
3329 }
3330
3331 /*
3332         Static send methods
3333 */
3334
3335 void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp)
3336 {
3337         DSTACK(__FUNCTION_NAME);
3338         std::ostringstream os(std::ios_base::binary);
3339
3340         writeU16(os, TOCLIENT_HP);
3341         writeU8(os, hp);
3342
3343         // Make data buffer
3344         std::string s = os.str();
3345         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3346         // Send as reliable
3347         con.Send(peer_id, 0, data, true);
3348 }
3349
3350 void Server::SendAccessDenied(con::Connection &con, u16 peer_id,
3351                 const std::wstring &reason)
3352 {
3353         DSTACK(__FUNCTION_NAME);
3354         std::ostringstream os(std::ios_base::binary);
3355
3356         writeU16(os, TOCLIENT_ACCESS_DENIED);
3357         os<<serializeWideString(reason);
3358
3359         // Make data buffer
3360         std::string s = os.str();
3361         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3362         // Send as reliable
3363         con.Send(peer_id, 0, data, true);
3364 }
3365
3366 void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
3367                 bool set_camera_point_target, v3f camera_point_target)
3368 {
3369         DSTACK(__FUNCTION_NAME);
3370         std::ostringstream os(std::ios_base::binary);
3371
3372         writeU16(os, TOCLIENT_DEATHSCREEN);
3373         writeU8(os, set_camera_point_target);
3374         writeV3F1000(os, camera_point_target);
3375
3376         // Make data buffer
3377         std::string s = os.str();
3378         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3379         // Send as reliable
3380         con.Send(peer_id, 0, data, true);
3381 }
3382
3383 void Server::SendItemDef(con::Connection &con, u16 peer_id,
3384                 IItemDefManager *itemdef)
3385 {
3386         DSTACK(__FUNCTION_NAME);
3387         std::ostringstream os(std::ios_base::binary);
3388
3389         /*
3390                 u16 command
3391                 u32 length of the next item
3392                 zlib-compressed serialized ItemDefManager
3393         */
3394         writeU16(os, TOCLIENT_ITEMDEF);
3395         std::ostringstream tmp_os(std::ios::binary);
3396         itemdef->serialize(tmp_os);
3397         std::ostringstream tmp_os2(std::ios::binary);
3398         compressZlib(tmp_os.str(), tmp_os2);
3399         os<<serializeLongString(tmp_os2.str());
3400
3401         // Make data buffer
3402         std::string s = os.str();
3403         verbosestream<<"Server: Sending item definitions to id("<<peer_id
3404                         <<"): size="<<s.size()<<std::endl;
3405         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3406         // Send as reliable
3407         con.Send(peer_id, 0, data, true);
3408 }
3409
3410 void Server::SendNodeDef(con::Connection &con, u16 peer_id,
3411                 INodeDefManager *nodedef)
3412 {
3413         DSTACK(__FUNCTION_NAME);
3414         std::ostringstream os(std::ios_base::binary);
3415
3416         /*
3417                 u16 command
3418                 u32 length of the next item
3419                 zlib-compressed serialized NodeDefManager
3420         */
3421         writeU16(os, TOCLIENT_NODEDEF);
3422         std::ostringstream tmp_os(std::ios::binary);
3423         nodedef->serialize(tmp_os);
3424         std::ostringstream tmp_os2(std::ios::binary);
3425         compressZlib(tmp_os.str(), tmp_os2);
3426         os<<serializeLongString(tmp_os2.str());
3427
3428         // Make data buffer
3429         std::string s = os.str();
3430         verbosestream<<"Server: Sending node definitions to id("<<peer_id
3431                         <<"): size="<<s.size()<<std::endl;
3432         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3433         // Send as reliable
3434         con.Send(peer_id, 0, data, true);
3435 }
3436
3437 /*
3438         Non-static send methods
3439 */
3440
3441 void Server::SendInventory(u16 peer_id)
3442 {
3443         DSTACK(__FUNCTION_NAME);
3444         
3445         ServerRemotePlayer* player =
3446                         static_cast<ServerRemotePlayer*>(m_env->getPlayer(peer_id));
3447         assert(player);
3448
3449         player->m_inventory_not_sent = false;
3450
3451         /*
3452                 Serialize it
3453         */
3454
3455         std::ostringstream os;
3456         //os.imbue(std::locale("C"));
3457
3458         player->inventory.serialize(os);
3459
3460         std::string s = os.str();
3461         
3462         SharedBuffer<u8> data(s.size()+2);
3463         writeU16(&data[0], TOCLIENT_INVENTORY);
3464         memcpy(&data[2], s.c_str(), s.size());
3465         
3466         // Send as reliable
3467         m_con.Send(peer_id, 0, data, true);
3468 }
3469
3470 void Server::SendWieldedItem(const ServerRemotePlayer* srp)
3471 {
3472         DSTACK(__FUNCTION_NAME);
3473
3474         assert(srp);
3475
3476         std::ostringstream os(std::ios_base::binary);
3477
3478         writeU16(os, TOCLIENT_PLAYERITEM);
3479         writeU16(os, 1);
3480         writeU16(os, srp->peer_id);
3481         os<<serializeString(srp->getWieldedItem().getItemString());
3482
3483         // Make data buffer
3484         std::string s = os.str();
3485         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3486
3487         m_con.SendToAll(0, data, true);
3488 }
3489
3490 void Server::SendPlayerItems()
3491 {
3492         DSTACK(__FUNCTION_NAME);
3493
3494         std::ostringstream os(std::ios_base::binary);
3495         core::list<Player *> players = m_env->getPlayers(true);
3496
3497         writeU16(os, TOCLIENT_PLAYERITEM);
3498         writeU16(os, players.size());
3499         core::list<Player *>::Iterator i;
3500         for(i = players.begin(); i != players.end(); ++i)
3501         {
3502                 Player *p = *i;
3503                 ServerRemotePlayer *srp =
3504                         static_cast<ServerRemotePlayer*>(p);
3505                 writeU16(os, p->peer_id);
3506                 os<<serializeString(srp->getWieldedItem().getItemString());
3507         }
3508
3509         // Make data buffer
3510         std::string s = os.str();
3511         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3512
3513         m_con.SendToAll(0, data, true);
3514 }
3515
3516 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
3517 {
3518         DSTACK(__FUNCTION_NAME);
3519         
3520         std::ostringstream os(std::ios_base::binary);
3521         u8 buf[12];
3522         
3523         // Write command
3524         writeU16(buf, TOCLIENT_CHAT_MESSAGE);
3525         os.write((char*)buf, 2);
3526         
3527         // Write length
3528         writeU16(buf, message.size());
3529         os.write((char*)buf, 2);
3530         
3531         // Write string
3532         for(u32 i=0; i<message.size(); i++)
3533         {
3534                 u16 w = message[i];
3535                 writeU16(buf, w);
3536                 os.write((char*)buf, 2);
3537         }
3538         
3539         // Make data buffer
3540         std::string s = os.str();
3541         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3542         // Send as reliable
3543         m_con.Send(peer_id, 0, data, true);
3544 }
3545
3546 void Server::BroadcastChatMessage(const std::wstring &message)
3547 {
3548         for(core::map<u16, RemoteClient*>::Iterator
3549                 i = m_clients.getIterator();
3550                 i.atEnd() == false; i++)
3551         {
3552                 // Get client and check that it is valid
3553                 RemoteClient *client = i.getNode()->getValue();
3554                 assert(client->peer_id == i.getNode()->getKey());
3555                 if(client->serialization_version == SER_FMT_VER_INVALID)
3556                         continue;
3557
3558                 SendChatMessage(client->peer_id, message);
3559         }
3560 }
3561
3562 void Server::SendPlayerHP(Player *player)
3563 {
3564         SendHP(m_con, player->peer_id, player->hp);
3565         static_cast<ServerRemotePlayer*>(player)->m_hp_not_sent = false;
3566 }
3567
3568 void Server::SendMovePlayer(Player *player)
3569 {
3570         DSTACK(__FUNCTION_NAME);
3571         std::ostringstream os(std::ios_base::binary);
3572
3573         writeU16(os, TOCLIENT_MOVE_PLAYER);
3574         writeV3F1000(os, player->getPosition());
3575         writeF1000(os, player->getPitch());
3576         writeF1000(os, player->getYaw());
3577         
3578         {
3579                 v3f pos = player->getPosition();
3580                 f32 pitch = player->getPitch();
3581                 f32 yaw = player->getYaw();
3582                 verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
3583                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3584                                 <<" pitch="<<pitch
3585                                 <<" yaw="<<yaw
3586                                 <<std::endl;
3587         }
3588
3589         // Make data buffer
3590         std::string s = os.str();
3591         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3592         // Send as reliable
3593         m_con.Send(player->peer_id, 0, data, true);
3594 }
3595
3596 s32 Server::playSound(const SimpleSoundSpec &spec,
3597                 const ServerSoundParams &params)
3598 {
3599         // Find out initial position of sound
3600         bool pos_exists = false;
3601         v3f pos = params.getPos(m_env, &pos_exists);
3602         // If position is not found while it should be, cancel sound
3603         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
3604                 return -1;
3605         // Filter destination clients
3606         std::set<RemoteClient*> dst_clients;
3607         if(params.to_player != "")
3608         {
3609                 Player *player = m_env->getPlayer(params.to_player.c_str());
3610                 if(!player){
3611                         infostream<<"Server::playSound: Player \""<<params.to_player
3612                                         <<"\" not found"<<std::endl;
3613                         return -1;
3614                 }
3615                 if(player->peer_id == PEER_ID_INEXISTENT){
3616                         infostream<<"Server::playSound: Player \""<<params.to_player
3617                                         <<"\" not connected"<<std::endl;
3618                         return -1;
3619                 }
3620                 RemoteClient *client = getClient(player->peer_id);
3621                 dst_clients.insert(client);
3622         }
3623         else
3624         {
3625                 for(core::map<u16, RemoteClient*>::Iterator
3626                                 i = m_clients.getIterator(); i.atEnd() == false; i++)
3627                 {
3628                         RemoteClient *client = i.getNode()->getValue();
3629                         Player *player = m_env->getPlayer(client->peer_id);
3630                         if(!player)
3631                                 continue;
3632                         if(pos_exists){
3633                                 if(player->getPosition().getDistanceFrom(pos) >
3634                                                 params.max_hear_distance)
3635                                         continue;
3636                         }
3637                         dst_clients.insert(client);
3638                 }
3639         }
3640         if(dst_clients.size() == 0)
3641                 return -1;
3642         // Create the sound
3643         s32 id = m_next_sound_id++;
3644         // The sound will exist as a reference in m_playing_sounds
3645         m_playing_sounds[id] = ServerPlayingSound();
3646         ServerPlayingSound &psound = m_playing_sounds[id];
3647         psound.params = params;
3648         for(std::set<RemoteClient*>::iterator i = dst_clients.begin();
3649                         i != dst_clients.end(); i++)
3650                 psound.clients.insert((*i)->peer_id);
3651         // Create packet
3652         std::ostringstream os(std::ios_base::binary);
3653         writeU16(os, TOCLIENT_PLAY_SOUND);
3654         writeS32(os, id);
3655         os<<serializeString(spec.name);
3656         writeF1000(os, spec.gain * params.gain);
3657         writeU8(os, params.type);
3658         writeV3F1000(os, pos);
3659         writeU16(os, params.object);
3660         writeU8(os, params.loop);
3661         // Make data buffer
3662         std::string s = os.str();
3663         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3664         // Send
3665         for(std::set<RemoteClient*>::iterator i = dst_clients.begin();
3666                         i != dst_clients.end(); i++){
3667                 // Send as reliable
3668                 m_con.Send((*i)->peer_id, 0, data, true);
3669         }
3670         return id;
3671 }
3672 void Server::stopSound(s32 handle)
3673 {
3674         // Get sound reference
3675         std::map<s32, ServerPlayingSound>::iterator i =
3676                         m_playing_sounds.find(handle);
3677         if(i == m_playing_sounds.end())
3678                 return;
3679         ServerPlayingSound &psound = i->second;
3680         // Create packet
3681         std::ostringstream os(std::ios_base::binary);
3682         writeU16(os, TOCLIENT_STOP_SOUND);
3683         writeS32(os, handle);
3684         // Make data buffer
3685         std::string s = os.str();
3686         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3687         // Send
3688         for(std::set<u16>::iterator i = psound.clients.begin();
3689                         i != psound.clients.end(); i++){
3690                 // Send as reliable
3691                 m_con.Send(*i, 0, data, true);
3692         }
3693         // Remove sound reference
3694         m_playing_sounds.erase(i);
3695 }
3696
3697 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
3698         core::list<u16> *far_players, float far_d_nodes)
3699 {
3700         float maxd = far_d_nodes*BS;
3701         v3f p_f = intToFloat(p, BS);
3702
3703         // Create packet
3704         u32 replysize = 8;
3705         SharedBuffer<u8> reply(replysize);
3706         writeU16(&reply[0], TOCLIENT_REMOVENODE);
3707         writeS16(&reply[2], p.X);
3708         writeS16(&reply[4], p.Y);
3709         writeS16(&reply[6], p.Z);
3710
3711         for(core::map<u16, RemoteClient*>::Iterator
3712                 i = m_clients.getIterator();
3713                 i.atEnd() == false; i++)
3714         {
3715                 // Get client and check that it is valid
3716                 RemoteClient *client = i.getNode()->getValue();
3717                 assert(client->peer_id == i.getNode()->getKey());
3718                 if(client->serialization_version == SER_FMT_VER_INVALID)
3719                         continue;
3720
3721                 // Don't send if it's the same one
3722                 if(client->peer_id == ignore_id)
3723                         continue;
3724                 
3725                 if(far_players)
3726                 {
3727                         // Get player
3728                         Player *player = m_env->getPlayer(client->peer_id);
3729                         if(player)
3730                         {
3731                                 // If player is far away, only set modified blocks not sent
3732                                 v3f player_pos = player->getPosition();
3733                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3734                                 {
3735                                         far_players->push_back(client->peer_id);
3736                                         continue;
3737                                 }
3738                         }
3739                 }
3740
3741                 // Send as reliable
3742                 m_con.Send(client->peer_id, 0, reply, true);
3743         }
3744 }
3745
3746 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
3747                 core::list<u16> *far_players, float far_d_nodes)
3748 {
3749         float maxd = far_d_nodes*BS;
3750         v3f p_f = intToFloat(p, BS);
3751
3752         for(core::map<u16, RemoteClient*>::Iterator
3753                 i = m_clients.getIterator();
3754                 i.atEnd() == false; i++)
3755         {
3756                 // Get client and check that it is valid
3757                 RemoteClient *client = i.getNode()->getValue();
3758                 assert(client->peer_id == i.getNode()->getKey());
3759                 if(client->serialization_version == SER_FMT_VER_INVALID)
3760                         continue;
3761
3762                 // Don't send if it's the same one
3763                 if(client->peer_id == ignore_id)
3764                         continue;
3765
3766                 if(far_players)
3767                 {
3768                         // Get player
3769                         Player *player = m_env->getPlayer(client->peer_id);
3770                         if(player)
3771                         {
3772                                 // If player is far away, only set modified blocks not sent
3773                                 v3f player_pos = player->getPosition();
3774                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3775                                 {
3776                                         far_players->push_back(client->peer_id);
3777                                         continue;
3778                                 }
3779                         }
3780                 }
3781
3782                 // Create packet
3783                 u32 replysize = 8 + MapNode::serializedLength(client->serialization_version);
3784                 SharedBuffer<u8> reply(replysize);
3785                 writeU16(&reply[0], TOCLIENT_ADDNODE);
3786                 writeS16(&reply[2], p.X);
3787                 writeS16(&reply[4], p.Y);
3788                 writeS16(&reply[6], p.Z);
3789                 n.serialize(&reply[8], client->serialization_version);
3790
3791                 // Send as reliable
3792                 m_con.Send(client->peer_id, 0, reply, true);
3793         }
3794 }
3795
3796 void Server::setBlockNotSent(v3s16 p)
3797 {
3798         for(core::map<u16, RemoteClient*>::Iterator
3799                 i = m_clients.getIterator();
3800                 i.atEnd()==false; i++)
3801         {
3802                 RemoteClient *client = i.getNode()->getValue();
3803                 client->SetBlockNotSent(p);
3804         }
3805 }
3806
3807 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
3808 {
3809         DSTACK(__FUNCTION_NAME);
3810
3811         v3s16 p = block->getPos();
3812         
3813 #if 0
3814         // Analyze it a bit
3815         bool completely_air = true;
3816         for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
3817         for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
3818         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
3819         {
3820                 if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
3821                 {
3822                         completely_air = false;
3823                         x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
3824                 }
3825         }
3826
3827         // Print result
3828         infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
3829         if(completely_air)
3830                 infostream<<"[completely air] ";
3831         infostream<<std::endl;
3832 #endif
3833
3834         /*
3835                 Create a packet with the block in the right format
3836         */
3837         
3838         std::ostringstream os(std::ios_base::binary);
3839         block->serialize(os, ver, false);
3840         std::string s = os.str();
3841         SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
3842
3843         u32 replysize = 8 + blockdata.getSize();
3844         SharedBuffer<u8> reply(replysize);
3845         writeU16(&reply[0], TOCLIENT_BLOCKDATA);
3846         writeS16(&reply[2], p.X);
3847         writeS16(&reply[4], p.Y);
3848         writeS16(&reply[6], p.Z);
3849         memcpy(&reply[8], *blockdata, blockdata.getSize());
3850
3851         /*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
3852                         <<":  \tpacket size: "<<replysize<<std::endl;*/
3853         
3854         /*
3855                 Send packet
3856         */
3857         m_con.Send(peer_id, 1, reply, true);
3858 }
3859
3860 void Server::SendBlocks(float dtime)
3861 {
3862         DSTACK(__FUNCTION_NAME);
3863
3864         JMutexAutoLock envlock(m_env_mutex);
3865         JMutexAutoLock conlock(m_con_mutex);
3866
3867         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
3868
3869         core::array<PrioritySortedBlockTransfer> queue;
3870
3871         s32 total_sending = 0;
3872         
3873         {
3874                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
3875
3876                 for(core::map<u16, RemoteClient*>::Iterator
3877                         i = m_clients.getIterator();
3878                         i.atEnd() == false; i++)
3879                 {
3880                         RemoteClient *client = i.getNode()->getValue();
3881                         assert(client->peer_id == i.getNode()->getKey());
3882
3883                         // If definitions and textures have not been sent, don't
3884                         // send MapBlocks either
3885                         if(!client->definitions_sent)
3886                                 continue;
3887
3888                         total_sending += client->SendingCount();
3889                         
3890                         if(client->serialization_version == SER_FMT_VER_INVALID)
3891                                 continue;
3892                         
3893                         client->GetNextBlocks(this, dtime, queue);
3894                 }
3895         }
3896
3897         // Sort.
3898         // Lowest priority number comes first.
3899         // Lowest is most important.
3900         queue.sort();
3901
3902         for(u32 i=0; i<queue.size(); i++)
3903         {
3904                 //TODO: Calculate limit dynamically
3905                 if(total_sending >= g_settings->getS32
3906                                 ("max_simultaneous_block_sends_server_total"))
3907                         break;
3908                 
3909                 PrioritySortedBlockTransfer q = queue[i];
3910
3911                 MapBlock *block = NULL;
3912                 try
3913                 {
3914                         block = m_env->getMap().getBlockNoCreate(q.pos);
3915                 }
3916                 catch(InvalidPositionException &e)
3917                 {
3918                         continue;
3919                 }
3920
3921                 RemoteClient *client = getClient(q.peer_id);
3922
3923                 SendBlockNoLock(q.peer_id, block, client->serialization_version);
3924
3925                 client->SentBlock(q.pos);
3926
3927                 total_sending++;
3928         }
3929 }
3930
3931 void Server::fillMediaCache()
3932 {
3933         DSTACK(__FUNCTION_NAME);
3934
3935         infostream<<"Server: Calculating media file checksums"<<std::endl;
3936         
3937         // Collect all media file paths
3938         std::list<std::string> paths;
3939         for(core::list<ModSpec>::Iterator i = m_mods.begin();
3940                         i != m_mods.end(); i++){
3941                 const ModSpec &mod = *i;
3942                 paths.push_back(mod.path + DIR_DELIM + "textures");
3943                 paths.push_back(mod.path + DIR_DELIM + "sounds");
3944                 paths.push_back(mod.path + DIR_DELIM + "media");
3945         }
3946         
3947         // Collect media file information from paths into cache
3948         for(std::list<std::string>::iterator i = paths.begin();
3949                         i != paths.end(); i++)
3950         {
3951                 std::string mediapath = *i;
3952                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
3953                 for(u32 j=0; j<dirlist.size(); j++){
3954                         if(dirlist[j].dir) // Ignode dirs
3955                                 continue;
3956                         std::string filename = dirlist[j].name;
3957                         // if name contains illegal characters, ignore the file
3958                         if(!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)){
3959                                 errorstream<<"Server: ignoring illegal file name: \""
3960                                                 <<filename<<"\""<<std::endl;
3961                                 continue;
3962                         }
3963                         std::string filepath = mediapath + DIR_DELIM + filename;
3964                         // Read data
3965                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
3966                         if(fis.good() == false){
3967                                 errorstream<<"Server::fillMediaCache(): Could not open \""
3968                                                 <<filename<<"\" for reading"<<std::endl;
3969                                 continue;
3970                         }
3971                         std::ostringstream tmp_os(std::ios_base::binary);
3972                         bool bad = false;
3973                         for(;;){
3974                                 char buf[1024];
3975                                 fis.read(buf, 1024);
3976                                 std::streamsize len = fis.gcount();
3977                                 tmp_os.write(buf, len);
3978                                 if(fis.eof())
3979                                         break;
3980                                 if(!fis.good()){
3981                                         bad = true;
3982                                         break;
3983                                 }
3984                         }
3985                         if(bad){
3986                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
3987                                                 <<filename<<"\""<<std::endl;
3988                                 continue;
3989                         }
3990                         if(tmp_os.str().length() == 0){
3991                                 errorstream<<"Server::fillMediaCache(): Empty file \""
3992                                                 <<filepath<<"\""<<std::endl;
3993                                 continue;
3994                         }
3995
3996                         SHA1 sha1;
3997                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
3998
3999                         unsigned char *digest = sha1.getDigest();
4000                         std::string sha1_base64 = base64_encode(digest, 20);
4001                         std::string sha1_hex = hex_encode((char*)digest, 20);
4002                         free(digest);
4003
4004                         // Put in list
4005                         this->m_media[filename] = MediaInfo(filepath, sha1_base64);
4006                         verbosestream<<"Server: "<<sha1_hex<<" is "<<filename<<std::endl;
4007                 }
4008         }
4009 }
4010
4011 struct SendableMediaAnnouncement
4012 {
4013         std::string name;
4014         std::string sha1_digest;
4015
4016         SendableMediaAnnouncement(const std::string name_="",
4017                         const std::string sha1_digest_=""):
4018                 name(name_),
4019                 sha1_digest(sha1_digest_)
4020         {}
4021 };
4022
4023 void Server::sendMediaAnnouncement(u16 peer_id)
4024 {
4025         DSTACK(__FUNCTION_NAME);
4026
4027         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
4028                         <<std::endl;
4029
4030         core::list<SendableMediaAnnouncement> file_announcements;
4031
4032         for(std::map<std::string, MediaInfo>::iterator i = m_media.begin();
4033                         i != m_media.end(); i++){
4034                 // Put in list
4035                 file_announcements.push_back(
4036                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
4037         }
4038
4039         // Make packet
4040         std::ostringstream os(std::ios_base::binary);
4041
4042         /*
4043                 u16 command
4044                 u32 number of files
4045                 for each texture {
4046                         u16 length of name
4047                         string name
4048                         u16 length of sha1_digest
4049                         string sha1_digest
4050                 }
4051         */
4052         
4053         writeU16(os, TOCLIENT_ANNOUNCE_MEDIA);
4054         writeU16(os, file_announcements.size());
4055
4056         for(core::list<SendableMediaAnnouncement>::Iterator
4057                         j = file_announcements.begin();
4058                         j != file_announcements.end(); j++){
4059                 os<<serializeString(j->name);
4060                 os<<serializeString(j->sha1_digest);
4061         }
4062
4063         // Make data buffer
4064         std::string s = os.str();
4065         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4066
4067         // Send as reliable
4068         m_con.Send(peer_id, 0, data, true);
4069
4070 }
4071
4072 struct SendableMedia
4073 {
4074         std::string name;
4075         std::string path;
4076         std::string data;
4077
4078         SendableMedia(const std::string &name_="", const std::string path_="",
4079                         const std::string &data_=""):
4080                 name(name_),
4081                 path(path_),
4082                 data(data_)
4083         {}
4084 };
4085
4086 void Server::sendRequestedMedia(u16 peer_id,
4087                 const core::list<MediaRequest> &tosend)
4088 {
4089         DSTACK(__FUNCTION_NAME);
4090
4091         verbosestream<<"Server::sendRequestedMedia(): "
4092                         <<"Sending files to client"<<std::endl;
4093
4094         /* Read files */
4095
4096         // Put 5kB in one bunch (this is not accurate)
4097         u32 bytes_per_bunch = 5000;
4098
4099         core::array< core::list<SendableMedia> > file_bunches;
4100         file_bunches.push_back(core::list<SendableMedia>());
4101
4102         u32 file_size_bunch_total = 0;
4103
4104         for(core::list<MediaRequest>::ConstIterator i = tosend.begin();
4105                         i != tosend.end(); i++)
4106         {
4107                 if(m_media.find(i->name) == m_media.end()){
4108                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
4109                                         <<"unknown file \""<<(i->name)<<"\""<<std::endl;
4110                         continue;
4111                 }
4112
4113                 //TODO get path + name
4114                 std::string tpath = m_media[(*i).name].path;
4115
4116                 // Read data
4117                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
4118                 if(fis.good() == false){
4119                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
4120                                         <<tpath<<"\" for reading"<<std::endl;
4121                         continue;
4122                 }
4123                 std::ostringstream tmp_os(std::ios_base::binary);
4124                 bool bad = false;
4125                 for(;;){
4126                         char buf[1024];
4127                         fis.read(buf, 1024);
4128                         std::streamsize len = fis.gcount();
4129                         tmp_os.write(buf, len);
4130                         file_size_bunch_total += len;
4131                         if(fis.eof())
4132                                 break;
4133                         if(!fis.good()){
4134                                 bad = true;
4135                                 break;
4136                         }
4137                 }
4138                 if(bad){
4139                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
4140                                         <<(*i).name<<"\""<<std::endl;
4141                         continue;
4142                 }
4143                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
4144                                 <<tname<<"\""<<std::endl;*/
4145                 // Put in list
4146                 file_bunches[file_bunches.size()-1].push_back(
4147                                 SendableMedia((*i).name, tpath, tmp_os.str()));
4148
4149                 // Start next bunch if got enough data
4150                 if(file_size_bunch_total >= bytes_per_bunch){
4151                         file_bunches.push_back(core::list<SendableMedia>());
4152                         file_size_bunch_total = 0;
4153                 }
4154
4155         }
4156
4157         /* Create and send packets */
4158
4159         u32 num_bunches = file_bunches.size();
4160         for(u32 i=0; i<num_bunches; i++)
4161         {
4162                 std::ostringstream os(std::ios_base::binary);
4163
4164                 /*
4165                         u16 command
4166                         u16 total number of texture bunches
4167                         u16 index of this bunch
4168                         u32 number of files in this bunch
4169                         for each file {
4170                                 u16 length of name
4171                                 string name
4172                                 u32 length of data
4173                                 data
4174                         }
4175                 */
4176
4177                 writeU16(os, TOCLIENT_MEDIA);
4178                 writeU16(os, num_bunches);
4179                 writeU16(os, i);
4180                 writeU32(os, file_bunches[i].size());
4181
4182                 for(core::list<SendableMedia>::Iterator
4183                                 j = file_bunches[i].begin();
4184                                 j != file_bunches[i].end(); j++){
4185                         os<<serializeString(j->name);
4186                         os<<serializeLongString(j->data);
4187                 }
4188
4189                 // Make data buffer
4190                 std::string s = os.str();
4191                 verbosestream<<"Server::sendRequestedMedia(): bunch "
4192                                 <<i<<"/"<<num_bunches
4193                                 <<" files="<<file_bunches[i].size()
4194                                 <<" size=" <<s.size()<<std::endl;
4195                 SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4196                 // Send as reliable
4197                 m_con.Send(peer_id, 0, data, true);
4198         }
4199 }
4200
4201 /*
4202         Something random
4203 */
4204
4205 void Server::DiePlayer(Player *player)
4206 {
4207         ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
4208
4209         infostream<<"Server::DiePlayer(): Player "
4210                         <<player->getName()<<" dies"<<std::endl;
4211         
4212         srp->setHP(0);
4213         
4214         // Trigger scripted stuff
4215         scriptapi_on_dieplayer(m_lua, srp);
4216         
4217         // Handle players that are not connected
4218         if(player->peer_id == PEER_ID_INEXISTENT){
4219                 RespawnPlayer(player);
4220                 return;
4221         }
4222
4223         SendPlayerHP(player);
4224         SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
4225 }
4226
4227 void Server::RespawnPlayer(Player *player)
4228 {
4229         ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
4230         srp->setHP(20);
4231         bool repositioned = scriptapi_on_respawnplayer(m_lua, srp);
4232         if(!repositioned){
4233                 v3f pos = findSpawnPos(m_env->getServerMap());
4234                 player->setPosition(pos);
4235                 srp->m_last_good_position = pos;
4236                 srp->m_last_good_position_age = 0;
4237         }
4238         SendMovePlayer(player);
4239         SendPlayerHP(player);
4240 }
4241
4242 void Server::UpdateCrafting(u16 peer_id)
4243 {
4244         DSTACK(__FUNCTION_NAME);
4245         
4246         Player* player = m_env->getPlayer(peer_id);
4247         assert(player);
4248
4249         // Get a preview for crafting
4250         ItemStack preview;
4251         // No crafting in creative mode
4252         if(g_settings->getBool("creative_mode") == false)
4253                 getCraftingResult(&player->inventory, preview, false, this);
4254
4255         // Put the new preview in
4256         InventoryList *plist = player->inventory.getList("craftpreview");
4257         assert(plist);
4258         assert(plist->getSize() >= 1);
4259         plist->changeItem(0, preview);
4260 }
4261
4262 RemoteClient* Server::getClient(u16 peer_id)
4263 {
4264         DSTACK(__FUNCTION_NAME);
4265         //JMutexAutoLock lock(m_con_mutex);
4266         core::map<u16, RemoteClient*>::Node *n;
4267         n = m_clients.find(peer_id);
4268         // A client should exist for all peers
4269         assert(n != NULL);
4270         return n->getValue();
4271 }
4272
4273 std::wstring Server::getStatusString()
4274 {
4275         std::wostringstream os(std::ios_base::binary);
4276         os<<L"# Server: ";
4277         // Version
4278         os<<L"version="<<narrow_to_wide(VERSION_STRING);
4279         // Uptime
4280         os<<L", uptime="<<m_uptime.get();
4281         // Information about clients
4282         os<<L", clients={";
4283         for(core::map<u16, RemoteClient*>::Iterator
4284                 i = m_clients.getIterator();
4285                 i.atEnd() == false; i++)
4286         {
4287                 // Get client and check that it is valid
4288                 RemoteClient *client = i.getNode()->getValue();
4289                 assert(client->peer_id == i.getNode()->getKey());
4290                 if(client->serialization_version == SER_FMT_VER_INVALID)
4291                         continue;
4292                 // Get player
4293                 Player *player = m_env->getPlayer(client->peer_id);
4294                 // Get name of player
4295                 std::wstring name = L"unknown";
4296                 if(player != NULL)
4297                         name = narrow_to_wide(player->getName());
4298                 // Add name to information string
4299                 os<<name<<L",";
4300         }
4301         os<<L"}";
4302         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
4303                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
4304         if(g_settings->get("motd") != "")
4305                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
4306         return os.str();
4307 }
4308
4309 u64 Server::getPlayerAuthPrivs(const std::string &name)
4310 {
4311         try{
4312                 return m_authmanager.getPrivs(name);
4313         }
4314         catch(AuthNotFoundException &e)
4315         {
4316                 dstream<<"WARNING: Auth not found for "<<name<<std::endl;
4317                 return 0;
4318         }
4319 }
4320
4321 void Server::setPlayerAuthPrivs(const std::string &name, u64 privs)
4322 {
4323         try{
4324                 return m_authmanager.setPrivs(name, privs);
4325         }
4326         catch(AuthNotFoundException &e)
4327         {
4328                 dstream<<"WARNING: Auth not found for "<<name<<std::endl;
4329         }
4330 }
4331
4332 u64 Server::getPlayerEffectivePrivs(const std::string &name)
4333 {
4334         // Local player gets all privileges regardless of
4335         // what's set on their account.
4336         if(m_simple_singleplayer_mode)
4337                 return PRIV_ALL;
4338         if(name == g_settings->get("name"))
4339                 return PRIV_ALL;
4340         return getPlayerAuthPrivs(name);
4341 }
4342
4343 void Server::setPlayerPassword(const std::string &name, const std::wstring &password)
4344 {
4345         // Add player to auth manager
4346         if(m_authmanager.exists(name) == false)
4347         {
4348                 infostream<<"Server: adding player "<<name
4349                                 <<" to auth manager"<<std::endl;
4350                 m_authmanager.add(name);
4351                 m_authmanager.setPrivs(name,
4352                         stringToPrivs(g_settings->get("default_privs")));
4353         }
4354         // Change password and save
4355         m_authmanager.setPassword(name, translatePassword(name, password));
4356         m_authmanager.save();
4357 }
4358
4359 // Saves g_settings to configpath given at initialization
4360 void Server::saveConfig()
4361 {
4362         if(m_path_config != "")
4363                 g_settings->updateConfigFile(m_path_config.c_str());
4364 }
4365
4366 void Server::notifyPlayer(const char *name, const std::wstring msg)
4367 {
4368         Player *player = m_env->getPlayer(name);
4369         if(!player)
4370                 return;
4371         SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
4372 }
4373
4374 void Server::notifyPlayers(const std::wstring msg)
4375 {
4376         BroadcastChatMessage(msg);
4377 }
4378
4379 void Server::queueBlockEmerge(v3s16 blockpos, bool allow_generate)
4380 {
4381         u8 flags = 0;
4382         if(!allow_generate)
4383                 flags |= BLOCK_EMERGE_FLAG_FROMDISK;
4384         m_emerge_queue.addBlock(PEER_ID_INEXISTENT, blockpos, flags);
4385 }
4386
4387 // IGameDef interface
4388 // Under envlock
4389 IItemDefManager* Server::getItemDefManager()
4390 {
4391         return m_itemdef;
4392 }
4393 INodeDefManager* Server::getNodeDefManager()
4394 {
4395         return m_nodedef;
4396 }
4397 ICraftDefManager* Server::getCraftDefManager()
4398 {
4399         return m_craftdef;
4400 }
4401 ITextureSource* Server::getTextureSource()
4402 {
4403         return NULL;
4404 }
4405 u16 Server::allocateUnknownNodeId(const std::string &name)
4406 {
4407         return m_nodedef->allocateDummy(name);
4408 }
4409 ISoundManager* Server::getSoundManager()
4410 {
4411         return &dummySoundManager;
4412 }
4413 MtEventManager* Server::getEventManager()
4414 {
4415         return m_event;
4416 }
4417
4418 IWritableItemDefManager* Server::getWritableItemDefManager()
4419 {
4420         return m_itemdef;
4421 }
4422 IWritableNodeDefManager* Server::getWritableNodeDefManager()
4423 {
4424         return m_nodedef;
4425 }
4426 IWritableCraftDefManager* Server::getWritableCraftDefManager()
4427 {
4428         return m_craftdef;
4429 }
4430
4431 const ModSpec* Server::getModSpec(const std::string &modname)
4432 {
4433         for(core::list<ModSpec>::Iterator i = m_mods.begin();
4434                         i != m_mods.end(); i++){
4435                 const ModSpec &mod = *i;
4436                 if(mod.name == modname)
4437                         return &mod;
4438         }
4439         return NULL;
4440 }
4441
4442 v3f findSpawnPos(ServerMap &map)
4443 {
4444         //return v3f(50,50,50)*BS;
4445
4446         v3s16 nodepos;
4447         
4448 #if 0
4449         nodepos = v2s16(0,0);
4450         groundheight = 20;
4451 #endif
4452
4453 #if 1
4454         // Try to find a good place a few times
4455         for(s32 i=0; i<1000; i++)
4456         {
4457                 s32 range = 1 + i;
4458                 // We're going to try to throw the player to this position
4459                 v2s16 nodepos2d = v2s16(-range + (myrand()%(range*2)),
4460                                 -range + (myrand()%(range*2)));
4461                 //v2s16 sectorpos = getNodeSectorPos(nodepos2d);
4462                 // Get ground height at point (fallbacks to heightmap function)
4463                 s16 groundheight = map.findGroundLevel(nodepos2d);
4464                 // Don't go underwater
4465                 if(groundheight < WATER_LEVEL)
4466                 {
4467                         //infostream<<"-> Underwater"<<std::endl;
4468                         continue;
4469                 }
4470                 // Don't go to high places
4471                 if(groundheight > WATER_LEVEL + 4)
4472                 {
4473                         //infostream<<"-> Underwater"<<std::endl;
4474                         continue;
4475                 }
4476                 
4477                 nodepos = v3s16(nodepos2d.X, groundheight-2, nodepos2d.Y);
4478                 bool is_good = false;
4479                 s32 air_count = 0;
4480                 for(s32 i=0; i<10; i++){
4481                         v3s16 blockpos = getNodeBlockPos(nodepos);
4482                         map.emergeBlock(blockpos, true);
4483                         MapNode n = map.getNodeNoEx(nodepos);
4484                         if(n.getContent() == CONTENT_AIR){
4485                                 air_count++;
4486                                 if(air_count >= 2){
4487                                         is_good = true;
4488                                         nodepos.Y -= 1;
4489                                         break;
4490                                 }
4491                         }
4492                         nodepos.Y++;
4493                 }
4494                 if(is_good){
4495                         // Found a good place
4496                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
4497                         break;
4498                 }
4499         }
4500 #endif
4501         
4502         return intToFloat(nodepos, BS);
4503 }
4504
4505 ServerRemotePlayer *Server::emergePlayer(const char *name, u16 peer_id)
4506 {
4507         /*
4508                 Try to get an existing player
4509         */
4510         ServerRemotePlayer *player =
4511                         static_cast<ServerRemotePlayer*>(m_env->getPlayer(name));
4512         if(player != NULL)
4513         {
4514                 // If player is already connected, cancel
4515                 if(player->peer_id != 0)
4516                 {
4517                         infostream<<"emergePlayer(): Player already connected"<<std::endl;
4518                         return NULL;
4519                 }
4520
4521                 // Got one.
4522                 player->peer_id = peer_id;
4523                 
4524                 // Re-add player to environment
4525                 if(player->m_removed)
4526                 {
4527                         player->m_removed = false;
4528                         player->setId(0);
4529                         m_env->addActiveObject(player);
4530                 }
4531
4532                 // Reset inventory to creative if in creative mode
4533                 if(g_settings->getBool("creative_mode"))
4534                 {
4535                         // Warning: double code below
4536                         // Backup actual inventory
4537                         player->inventory_backup = new Inventory(m_itemdef);
4538                         *(player->inventory_backup) = player->inventory;
4539                         // Set creative inventory
4540                         player->resetInventory();
4541                         scriptapi_get_creative_inventory(m_lua, player);
4542                 }
4543
4544                 return player;
4545         }
4546
4547         /*
4548                 If player with the wanted peer_id already exists, cancel.
4549         */
4550         if(m_env->getPlayer(peer_id) != NULL)
4551         {
4552                 infostream<<"emergePlayer(): Player with wrong name but same"
4553                                 " peer_id already exists"<<std::endl;
4554                 return NULL;
4555         }
4556         
4557         /*
4558                 Create a new player
4559         */
4560         {
4561                 /* Set player position */
4562                 
4563                 infostream<<"Server: Finding spawn place for player \""
4564                                 <<name<<"\""<<std::endl;
4565
4566                 v3f pos = findSpawnPos(m_env->getServerMap());
4567
4568                 player = new ServerRemotePlayer(m_env, pos, peer_id, name);
4569                 ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
4570
4571                 /* Add player to environment */
4572                 m_env->addPlayer(player);
4573                 m_env->addActiveObject(srp);
4574
4575                 /* Run scripts */
4576                 scriptapi_on_newplayer(m_lua, srp);
4577
4578                 /* Add stuff to inventory */
4579                 if(g_settings->getBool("creative_mode"))
4580                 {
4581                         // Warning: double code above
4582                         // Backup actual inventory
4583                         player->inventory_backup = new Inventory(m_itemdef);
4584                         *(player->inventory_backup) = player->inventory;
4585                         // Set creative inventory
4586                         player->resetInventory();
4587                         scriptapi_get_creative_inventory(m_lua, player);
4588                 }
4589
4590                 return player;
4591                 
4592         } // create new player
4593 }
4594
4595 void Server::handlePeerChange(PeerChange &c)
4596 {
4597         JMutexAutoLock envlock(m_env_mutex);
4598         JMutexAutoLock conlock(m_con_mutex);
4599         
4600         if(c.type == PEER_ADDED)
4601         {
4602                 /*
4603                         Add
4604                 */
4605
4606                 // Error check
4607                 core::map<u16, RemoteClient*>::Node *n;
4608                 n = m_clients.find(c.peer_id);
4609                 // The client shouldn't already exist
4610                 assert(n == NULL);
4611
4612                 // Create client
4613                 RemoteClient *client = new RemoteClient();
4614                 client->peer_id = c.peer_id;
4615                 m_clients.insert(client->peer_id, client);
4616
4617         } // PEER_ADDED
4618         else if(c.type == PEER_REMOVED)
4619         {
4620                 /*
4621                         Delete
4622                 */
4623
4624                 // Error check
4625                 core::map<u16, RemoteClient*>::Node *n;
4626                 n = m_clients.find(c.peer_id);
4627                 // The client should exist
4628                 assert(n != NULL);
4629                 
4630                 /*
4631                         Mark objects to be not known by the client
4632                 */
4633                 RemoteClient *client = n->getValue();
4634                 // Handle objects
4635                 for(core::map<u16, bool>::Iterator
4636                                 i = client->m_known_objects.getIterator();
4637                                 i.atEnd()==false; i++)
4638                 {
4639                         // Get object
4640                         u16 id = i.getNode()->getKey();
4641                         ServerActiveObject* obj = m_env->getActiveObject(id);
4642                         
4643                         if(obj && obj->m_known_by_count > 0)
4644                                 obj->m_known_by_count--;
4645                 }
4646
4647                 /*
4648                         Clear references to playing sounds
4649                 */
4650                 for(std::map<s32, ServerPlayingSound>::iterator
4651                                 i = m_playing_sounds.begin();
4652                                 i != m_playing_sounds.end();)
4653                 {
4654                         ServerPlayingSound &psound = i->second;
4655                         psound.clients.erase(c.peer_id);
4656                         if(psound.clients.size() == 0)
4657                                 m_playing_sounds.erase(i++);
4658                         else
4659                                 i++;
4660                 }
4661
4662                 ServerRemotePlayer* player =
4663                                 static_cast<ServerRemotePlayer*>(m_env->getPlayer(c.peer_id));
4664
4665                 // Collect information about leaving in chat
4666                 std::wstring message;
4667                 {
4668                         if(player != NULL)
4669                         {
4670                                 std::wstring name = narrow_to_wide(player->getName());
4671                                 message += L"*** ";
4672                                 message += name;
4673                                 message += L" left game";
4674                                 if(c.timeout)
4675                                         message += L" (timed out)";
4676                         }
4677                 }
4678                 
4679                 // Remove from environment
4680                 if(player != NULL)
4681                         player->m_removed = true;
4682                 
4683                 // Set player client disconnected
4684                 if(player != NULL)
4685                         player->peer_id = 0;
4686         
4687                 /*
4688                         Print out action
4689                 */
4690                 {
4691                         if(player != NULL)
4692                         {
4693                                 std::ostringstream os(std::ios_base::binary);
4694                                 for(core::map<u16, RemoteClient*>::Iterator
4695                                         i = m_clients.getIterator();
4696                                         i.atEnd() == false; i++)
4697                                 {
4698                                         RemoteClient *client = i.getNode()->getValue();
4699                                         assert(client->peer_id == i.getNode()->getKey());
4700                                         if(client->serialization_version == SER_FMT_VER_INVALID)
4701                                                 continue;
4702                                         // Get player
4703                                         Player *player = m_env->getPlayer(client->peer_id);
4704                                         if(!player)
4705                                                 continue;
4706                                         // Get name of player
4707                                         os<<player->getName()<<" ";
4708                                 }
4709
4710                                 actionstream<<player->getName()<<" "
4711                                                 <<(c.timeout?"times out.":"leaves game.")
4712                                                 <<" List of players: "
4713                                                 <<os.str()<<std::endl;
4714                         }
4715                 }
4716                 
4717                 // Delete client
4718                 delete m_clients[c.peer_id];
4719                 m_clients.remove(c.peer_id);
4720
4721                 // Send player info to all remaining clients
4722                 //SendPlayerInfos();
4723                 
4724                 // Send leave chat message to all remaining clients
4725                 if(message.length() != 0)
4726                         BroadcastChatMessage(message);
4727                 
4728         } // PEER_REMOVED
4729         else
4730         {
4731                 assert(0);
4732         }
4733 }
4734
4735 void Server::handlePeerChanges()
4736 {
4737         while(m_peer_change_queue.size() > 0)
4738         {
4739                 PeerChange c = m_peer_change_queue.pop_front();
4740
4741                 verbosestream<<"Server: Handling peer change: "
4742                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
4743                                 <<std::endl;
4744
4745                 handlePeerChange(c);
4746         }
4747 }
4748
4749 u64 Server::getPlayerPrivs(Player *player)
4750 {
4751         if(player==NULL)
4752                 return 0;
4753         std::string playername = player->getName();
4754         return getPlayerEffectivePrivs(playername);
4755 }
4756
4757 void dedicated_server_loop(Server &server, bool &kill)
4758 {
4759         DSTACK(__FUNCTION_NAME);
4760         
4761         verbosestream<<"dedicated_server_loop()"<<std::endl;
4762
4763         IntervalLimiter m_profiler_interval;
4764
4765         for(;;)
4766         {
4767                 float steplen = g_settings->getFloat("dedicated_server_step");
4768                 // This is kind of a hack but can be done like this
4769                 // because server.step() is very light
4770                 {
4771                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
4772                         sleep_ms((int)(steplen*1000.0));
4773                 }
4774                 server.step(steplen);
4775
4776                 if(server.getShutdownRequested() || kill)
4777                 {
4778                         infostream<<"Dedicated server quitting"<<std::endl;
4779                         break;
4780                 }
4781
4782                 /*
4783                         Profiler
4784                 */
4785                 float profiler_print_interval =
4786                                 g_settings->getFloat("profiler_print_interval");
4787                 if(profiler_print_interval != 0)
4788                 {
4789                         if(m_profiler_interval.step(steplen, profiler_print_interval))
4790                         {
4791                                 infostream<<"Profiler:"<<std::endl;
4792                                 g_profiler->print(infostream);
4793                                 g_profiler->clear();
4794                         }
4795                 }
4796         }
4797 }
4798
4799