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