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