]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Add event manager and use it to trigger sounds
[dragonfireclient.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
3130         {
3131                 infostream<<"Server::ProcessData(): Ignoring "
3132                                 "unknown command "<<command<<std::endl;
3133         }
3134         
3135         } //try
3136         catch(SendFailedException &e)
3137         {
3138                 errorstream<<"Server::ProcessData(): SendFailedException: "
3139                                 <<"what="<<e.what()
3140                                 <<std::endl;
3141         }
3142 }
3143
3144 void Server::onMapEditEvent(MapEditEvent *event)
3145 {
3146         //infostream<<"Server::onMapEditEvent()"<<std::endl;
3147         if(m_ignore_map_edit_events)
3148                 return;
3149         MapEditEvent *e = event->clone();
3150         m_unsent_map_edit_queue.push_back(e);
3151 }
3152
3153 Inventory* Server::getInventory(const InventoryLocation &loc)
3154 {
3155         switch(loc.type){
3156         case InventoryLocation::UNDEFINED:
3157         {}
3158         break;
3159         case InventoryLocation::CURRENT_PLAYER:
3160         {}
3161         break;
3162         case InventoryLocation::PLAYER:
3163         {
3164                 Player *player = m_env->getPlayer(loc.name.c_str());
3165                 if(!player)
3166                         return NULL;
3167                 return &player->inventory;
3168         }
3169         break;
3170         case InventoryLocation::NODEMETA:
3171         {
3172                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3173                 if(!meta)
3174                         return NULL;
3175                 return meta->getInventory();
3176         }
3177         break;
3178         default:
3179                 assert(0);
3180         }
3181         return NULL;
3182 }
3183 std::string Server::getInventoryOwner(const InventoryLocation &loc)
3184 {
3185         switch(loc.type){
3186         case InventoryLocation::UNDEFINED:
3187         {}
3188         break;
3189         case InventoryLocation::CURRENT_PLAYER:
3190         {}
3191         break;
3192         case InventoryLocation::PLAYER:
3193         {
3194                 return loc.name;
3195         }
3196         break;
3197         case InventoryLocation::NODEMETA:
3198         {
3199                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3200                 if(!meta)
3201                         return "";
3202                 return meta->getOwner();
3203         }
3204         break;
3205         default:
3206                 assert(0);
3207         }
3208         return "";
3209 }
3210 void Server::setInventoryModified(const InventoryLocation &loc)
3211 {
3212         switch(loc.type){
3213         case InventoryLocation::UNDEFINED:
3214         {}
3215         break;
3216         case InventoryLocation::PLAYER:
3217         {
3218                 ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>
3219                                 (m_env->getPlayer(loc.name.c_str()));
3220                 if(!srp)
3221                         return;
3222                 srp->m_inventory_not_sent = true;
3223         }
3224         break;
3225         case InventoryLocation::NODEMETA:
3226         {
3227                 v3s16 blockpos = getNodeBlockPos(loc.p);
3228
3229                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3230                 if(meta)
3231                         meta->inventoryModified();
3232                 
3233                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
3234                 if(block)
3235                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
3236                 
3237                 setBlockNotSent(blockpos);
3238         }
3239         break;
3240         default:
3241                 assert(0);
3242         }
3243 }
3244
3245 core::list<PlayerInfo> Server::getPlayerInfo()
3246 {
3247         DSTACK(__FUNCTION_NAME);
3248         JMutexAutoLock envlock(m_env_mutex);
3249         JMutexAutoLock conlock(m_con_mutex);
3250         
3251         core::list<PlayerInfo> list;
3252
3253         core::list<Player*> players = m_env->getPlayers();
3254         
3255         core::list<Player*>::Iterator i;
3256         for(i = players.begin();
3257                         i != players.end(); i++)
3258         {
3259                 PlayerInfo info;
3260
3261                 Player *player = *i;
3262
3263                 try{
3264                         // Copy info from connection to info struct
3265                         info.id = player->peer_id;
3266                         info.address = m_con.GetPeerAddress(player->peer_id);
3267                         info.avg_rtt = m_con.GetPeerAvgRTT(player->peer_id);
3268                 }
3269                 catch(con::PeerNotFoundException &e)
3270                 {
3271                         // Set dummy peer info
3272                         info.id = 0;
3273                         info.address = Address(0,0,0,0,0);
3274                         info.avg_rtt = 0.0;
3275                 }
3276
3277                 snprintf(info.name, PLAYERNAME_SIZE, "%s", player->getName());
3278                 info.position = player->getPosition();
3279
3280                 list.push_back(info);
3281         }
3282
3283         return list;
3284 }
3285
3286
3287 void Server::peerAdded(con::Peer *peer)
3288 {
3289         DSTACK(__FUNCTION_NAME);
3290         verbosestream<<"Server::peerAdded(): peer->id="
3291                         <<peer->id<<std::endl;
3292         
3293         PeerChange c;
3294         c.type = PEER_ADDED;
3295         c.peer_id = peer->id;
3296         c.timeout = false;
3297         m_peer_change_queue.push_back(c);
3298 }
3299
3300 void Server::deletingPeer(con::Peer *peer, bool timeout)
3301 {
3302         DSTACK(__FUNCTION_NAME);
3303         verbosestream<<"Server::deletingPeer(): peer->id="
3304                         <<peer->id<<", timeout="<<timeout<<std::endl;
3305         
3306         PeerChange c;
3307         c.type = PEER_REMOVED;
3308         c.peer_id = peer->id;
3309         c.timeout = timeout;
3310         m_peer_change_queue.push_back(c);
3311 }
3312
3313 /*
3314         Static send methods
3315 */
3316
3317 void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp)
3318 {
3319         DSTACK(__FUNCTION_NAME);
3320         std::ostringstream os(std::ios_base::binary);
3321
3322         writeU16(os, TOCLIENT_HP);
3323         writeU8(os, hp);
3324
3325         // Make data buffer
3326         std::string s = os.str();
3327         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3328         // Send as reliable
3329         con.Send(peer_id, 0, data, true);
3330 }
3331
3332 void Server::SendAccessDenied(con::Connection &con, u16 peer_id,
3333                 const std::wstring &reason)
3334 {
3335         DSTACK(__FUNCTION_NAME);
3336         std::ostringstream os(std::ios_base::binary);
3337
3338         writeU16(os, TOCLIENT_ACCESS_DENIED);
3339         os<<serializeWideString(reason);
3340
3341         // Make data buffer
3342         std::string s = os.str();
3343         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3344         // Send as reliable
3345         con.Send(peer_id, 0, data, true);
3346 }
3347
3348 void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
3349                 bool set_camera_point_target, v3f camera_point_target)
3350 {
3351         DSTACK(__FUNCTION_NAME);
3352         std::ostringstream os(std::ios_base::binary);
3353
3354         writeU16(os, TOCLIENT_DEATHSCREEN);
3355         writeU8(os, set_camera_point_target);
3356         writeV3F1000(os, camera_point_target);
3357
3358         // Make data buffer
3359         std::string s = os.str();
3360         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3361         // Send as reliable
3362         con.Send(peer_id, 0, data, true);
3363 }
3364
3365 void Server::SendItemDef(con::Connection &con, u16 peer_id,
3366                 IItemDefManager *itemdef)
3367 {
3368         DSTACK(__FUNCTION_NAME);
3369         std::ostringstream os(std::ios_base::binary);
3370
3371         /*
3372                 u16 command
3373                 u32 length of the next item
3374                 zlib-compressed serialized ItemDefManager
3375         */
3376         writeU16(os, TOCLIENT_ITEMDEF);
3377         std::ostringstream tmp_os(std::ios::binary);
3378         itemdef->serialize(tmp_os);
3379         std::ostringstream tmp_os2(std::ios::binary);
3380         compressZlib(tmp_os.str(), tmp_os2);
3381         os<<serializeLongString(tmp_os2.str());
3382
3383         // Make data buffer
3384         std::string s = os.str();
3385         verbosestream<<"Server: Sending item definitions to id("<<peer_id
3386                         <<"): size="<<s.size()<<std::endl;
3387         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3388         // Send as reliable
3389         con.Send(peer_id, 0, data, true);
3390 }
3391
3392 void Server::SendNodeDef(con::Connection &con, u16 peer_id,
3393                 INodeDefManager *nodedef)
3394 {
3395         DSTACK(__FUNCTION_NAME);
3396         std::ostringstream os(std::ios_base::binary);
3397
3398         /*
3399                 u16 command
3400                 u32 length of the next item
3401                 zlib-compressed serialized NodeDefManager
3402         */
3403         writeU16(os, TOCLIENT_NODEDEF);
3404         std::ostringstream tmp_os(std::ios::binary);
3405         nodedef->serialize(tmp_os);
3406         std::ostringstream tmp_os2(std::ios::binary);
3407         compressZlib(tmp_os.str(), tmp_os2);
3408         os<<serializeLongString(tmp_os2.str());
3409
3410         // Make data buffer
3411         std::string s = os.str();
3412         verbosestream<<"Server: Sending node definitions to id("<<peer_id
3413                         <<"): size="<<s.size()<<std::endl;
3414         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3415         // Send as reliable
3416         con.Send(peer_id, 0, data, true);
3417 }
3418
3419 /*
3420         Non-static send methods
3421 */
3422
3423 void Server::SendInventory(u16 peer_id)
3424 {
3425         DSTACK(__FUNCTION_NAME);
3426         
3427         ServerRemotePlayer* player =
3428                         static_cast<ServerRemotePlayer*>(m_env->getPlayer(peer_id));
3429         assert(player);
3430
3431         player->m_inventory_not_sent = false;
3432
3433         /*
3434                 Serialize it
3435         */
3436
3437         std::ostringstream os;
3438         //os.imbue(std::locale("C"));
3439
3440         player->inventory.serialize(os);
3441
3442         std::string s = os.str();
3443         
3444         SharedBuffer<u8> data(s.size()+2);
3445         writeU16(&data[0], TOCLIENT_INVENTORY);
3446         memcpy(&data[2], s.c_str(), s.size());
3447         
3448         // Send as reliable
3449         m_con.Send(peer_id, 0, data, true);
3450 }
3451
3452 void Server::SendWieldedItem(const ServerRemotePlayer* srp)
3453 {
3454         DSTACK(__FUNCTION_NAME);
3455
3456         assert(srp);
3457
3458         std::ostringstream os(std::ios_base::binary);
3459
3460         writeU16(os, TOCLIENT_PLAYERITEM);
3461         writeU16(os, 1);
3462         writeU16(os, srp->peer_id);
3463         os<<serializeString(srp->getWieldedItem().getItemString());
3464
3465         // Make data buffer
3466         std::string s = os.str();
3467         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3468
3469         m_con.SendToAll(0, data, true);
3470 }
3471
3472 void Server::SendPlayerItems()
3473 {
3474         DSTACK(__FUNCTION_NAME);
3475
3476         std::ostringstream os(std::ios_base::binary);
3477         core::list<Player *> players = m_env->getPlayers(true);
3478
3479         writeU16(os, TOCLIENT_PLAYERITEM);
3480         writeU16(os, players.size());
3481         core::list<Player *>::Iterator i;
3482         for(i = players.begin(); i != players.end(); ++i)
3483         {
3484                 Player *p = *i;
3485                 ServerRemotePlayer *srp =
3486                         static_cast<ServerRemotePlayer*>(p);
3487                 writeU16(os, p->peer_id);
3488                 os<<serializeString(srp->getWieldedItem().getItemString());
3489         }
3490
3491         // Make data buffer
3492         std::string s = os.str();
3493         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3494
3495         m_con.SendToAll(0, data, true);
3496 }
3497
3498 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
3499 {
3500         DSTACK(__FUNCTION_NAME);
3501         
3502         std::ostringstream os(std::ios_base::binary);
3503         u8 buf[12];
3504         
3505         // Write command
3506         writeU16(buf, TOCLIENT_CHAT_MESSAGE);
3507         os.write((char*)buf, 2);
3508         
3509         // Write length
3510         writeU16(buf, message.size());
3511         os.write((char*)buf, 2);
3512         
3513         // Write string
3514         for(u32 i=0; i<message.size(); i++)
3515         {
3516                 u16 w = message[i];
3517                 writeU16(buf, w);
3518                 os.write((char*)buf, 2);
3519         }
3520         
3521         // Make data buffer
3522         std::string s = os.str();
3523         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3524         // Send as reliable
3525         m_con.Send(peer_id, 0, data, true);
3526 }
3527
3528 void Server::BroadcastChatMessage(const std::wstring &message)
3529 {
3530         for(core::map<u16, RemoteClient*>::Iterator
3531                 i = m_clients.getIterator();
3532                 i.atEnd() == false; i++)
3533         {
3534                 // Get client and check that it is valid
3535                 RemoteClient *client = i.getNode()->getValue();
3536                 assert(client->peer_id == i.getNode()->getKey());
3537                 if(client->serialization_version == SER_FMT_VER_INVALID)
3538                         continue;
3539
3540                 SendChatMessage(client->peer_id, message);
3541         }
3542 }
3543
3544 void Server::SendPlayerHP(Player *player)
3545 {
3546         SendHP(m_con, player->peer_id, player->hp);
3547         static_cast<ServerRemotePlayer*>(player)->m_hp_not_sent = false;
3548 }
3549
3550 void Server::SendMovePlayer(Player *player)
3551 {
3552         DSTACK(__FUNCTION_NAME);
3553         std::ostringstream os(std::ios_base::binary);
3554
3555         writeU16(os, TOCLIENT_MOVE_PLAYER);
3556         writeV3F1000(os, player->getPosition());
3557         writeF1000(os, player->getPitch());
3558         writeF1000(os, player->getYaw());
3559         
3560         {
3561                 v3f pos = player->getPosition();
3562                 f32 pitch = player->getPitch();
3563                 f32 yaw = player->getYaw();
3564                 verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
3565                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3566                                 <<" pitch="<<pitch
3567                                 <<" yaw="<<yaw
3568                                 <<std::endl;
3569         }
3570
3571         // Make data buffer
3572         std::string s = os.str();
3573         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3574         // Send as reliable
3575         m_con.Send(player->peer_id, 0, data, true);
3576 }
3577
3578 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
3579         core::list<u16> *far_players, float far_d_nodes)
3580 {
3581         float maxd = far_d_nodes*BS;
3582         v3f p_f = intToFloat(p, BS);
3583
3584         // Create packet
3585         u32 replysize = 8;
3586         SharedBuffer<u8> reply(replysize);
3587         writeU16(&reply[0], TOCLIENT_REMOVENODE);
3588         writeS16(&reply[2], p.X);
3589         writeS16(&reply[4], p.Y);
3590         writeS16(&reply[6], p.Z);
3591
3592         for(core::map<u16, RemoteClient*>::Iterator
3593                 i = m_clients.getIterator();
3594                 i.atEnd() == false; i++)
3595         {
3596                 // Get client and check that it is valid
3597                 RemoteClient *client = i.getNode()->getValue();
3598                 assert(client->peer_id == i.getNode()->getKey());
3599                 if(client->serialization_version == SER_FMT_VER_INVALID)
3600                         continue;
3601
3602                 // Don't send if it's the same one
3603                 if(client->peer_id == ignore_id)
3604                         continue;
3605                 
3606                 if(far_players)
3607                 {
3608                         // Get player
3609                         Player *player = m_env->getPlayer(client->peer_id);
3610                         if(player)
3611                         {
3612                                 // If player is far away, only set modified blocks not sent
3613                                 v3f player_pos = player->getPosition();
3614                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3615                                 {
3616                                         far_players->push_back(client->peer_id);
3617                                         continue;
3618                                 }
3619                         }
3620                 }
3621
3622                 // Send as reliable
3623                 m_con.Send(client->peer_id, 0, reply, true);
3624         }
3625 }
3626
3627 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
3628                 core::list<u16> *far_players, float far_d_nodes)
3629 {
3630         float maxd = far_d_nodes*BS;
3631         v3f p_f = intToFloat(p, BS);
3632
3633         for(core::map<u16, RemoteClient*>::Iterator
3634                 i = m_clients.getIterator();
3635                 i.atEnd() == false; i++)
3636         {
3637                 // Get client and check that it is valid
3638                 RemoteClient *client = i.getNode()->getValue();
3639                 assert(client->peer_id == i.getNode()->getKey());
3640                 if(client->serialization_version == SER_FMT_VER_INVALID)
3641                         continue;
3642
3643                 // Don't send if it's the same one
3644                 if(client->peer_id == ignore_id)
3645                         continue;
3646
3647                 if(far_players)
3648                 {
3649                         // Get player
3650                         Player *player = m_env->getPlayer(client->peer_id);
3651                         if(player)
3652                         {
3653                                 // If player is far away, only set modified blocks not sent
3654                                 v3f player_pos = player->getPosition();
3655                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3656                                 {
3657                                         far_players->push_back(client->peer_id);
3658                                         continue;
3659                                 }
3660                         }
3661                 }
3662
3663                 // Create packet
3664                 u32 replysize = 8 + MapNode::serializedLength(client->serialization_version);
3665                 SharedBuffer<u8> reply(replysize);
3666                 writeU16(&reply[0], TOCLIENT_ADDNODE);
3667                 writeS16(&reply[2], p.X);
3668                 writeS16(&reply[4], p.Y);
3669                 writeS16(&reply[6], p.Z);
3670                 n.serialize(&reply[8], client->serialization_version);
3671
3672                 // Send as reliable
3673                 m_con.Send(client->peer_id, 0, reply, true);
3674         }
3675 }
3676
3677 void Server::setBlockNotSent(v3s16 p)
3678 {
3679         for(core::map<u16, RemoteClient*>::Iterator
3680                 i = m_clients.getIterator();
3681                 i.atEnd()==false; i++)
3682         {
3683                 RemoteClient *client = i.getNode()->getValue();
3684                 client->SetBlockNotSent(p);
3685         }
3686 }
3687
3688 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
3689 {
3690         DSTACK(__FUNCTION_NAME);
3691
3692         v3s16 p = block->getPos();
3693         
3694 #if 0
3695         // Analyze it a bit
3696         bool completely_air = true;
3697         for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
3698         for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
3699         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
3700         {
3701                 if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
3702                 {
3703                         completely_air = false;
3704                         x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
3705                 }
3706         }
3707
3708         // Print result
3709         infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
3710         if(completely_air)
3711                 infostream<<"[completely air] ";
3712         infostream<<std::endl;
3713 #endif
3714
3715         /*
3716                 Create a packet with the block in the right format
3717         */
3718         
3719         std::ostringstream os(std::ios_base::binary);
3720         block->serialize(os, ver, false);
3721         std::string s = os.str();
3722         SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
3723
3724         u32 replysize = 8 + blockdata.getSize();
3725         SharedBuffer<u8> reply(replysize);
3726         writeU16(&reply[0], TOCLIENT_BLOCKDATA);
3727         writeS16(&reply[2], p.X);
3728         writeS16(&reply[4], p.Y);
3729         writeS16(&reply[6], p.Z);
3730         memcpy(&reply[8], *blockdata, blockdata.getSize());
3731
3732         /*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
3733                         <<":  \tpacket size: "<<replysize<<std::endl;*/
3734         
3735         /*
3736                 Send packet
3737         */
3738         m_con.Send(peer_id, 1, reply, true);
3739 }
3740
3741 void Server::SendBlocks(float dtime)
3742 {
3743         DSTACK(__FUNCTION_NAME);
3744
3745         JMutexAutoLock envlock(m_env_mutex);
3746         JMutexAutoLock conlock(m_con_mutex);
3747
3748         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
3749
3750         core::array<PrioritySortedBlockTransfer> queue;
3751
3752         s32 total_sending = 0;
3753         
3754         {
3755                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
3756
3757                 for(core::map<u16, RemoteClient*>::Iterator
3758                         i = m_clients.getIterator();
3759                         i.atEnd() == false; i++)
3760                 {
3761                         RemoteClient *client = i.getNode()->getValue();
3762                         assert(client->peer_id == i.getNode()->getKey());
3763
3764                         // If definitions and textures have not been sent, don't
3765                         // send MapBlocks either
3766                         if(!client->definitions_sent)
3767                                 continue;
3768
3769                         total_sending += client->SendingCount();
3770                         
3771                         if(client->serialization_version == SER_FMT_VER_INVALID)
3772                                 continue;
3773                         
3774                         client->GetNextBlocks(this, dtime, queue);
3775                 }
3776         }
3777
3778         // Sort.
3779         // Lowest priority number comes first.
3780         // Lowest is most important.
3781         queue.sort();
3782
3783         for(u32 i=0; i<queue.size(); i++)
3784         {
3785                 //TODO: Calculate limit dynamically
3786                 if(total_sending >= g_settings->getS32
3787                                 ("max_simultaneous_block_sends_server_total"))
3788                         break;
3789                 
3790                 PrioritySortedBlockTransfer q = queue[i];
3791
3792                 MapBlock *block = NULL;
3793                 try
3794                 {
3795                         block = m_env->getMap().getBlockNoCreate(q.pos);
3796                 }
3797                 catch(InvalidPositionException &e)
3798                 {
3799                         continue;
3800                 }
3801
3802                 RemoteClient *client = getClient(q.peer_id);
3803
3804                 SendBlockNoLock(q.peer_id, block, client->serialization_version);
3805
3806                 client->SentBlock(q.pos);
3807
3808                 total_sending++;
3809         }
3810 }
3811
3812 void Server::PrepareTextures()
3813 {
3814         DSTACK(__FUNCTION_NAME);
3815
3816         infostream<<"Server: Calculating texture checksums"<<std::endl;
3817
3818         for(core::list<ModSpec>::Iterator i = m_mods.begin();
3819                         i != m_mods.end(); i++){
3820                 const ModSpec &mod = *i;
3821                 std::string texturepath = mod.path + DIR_DELIM + "textures";
3822                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(texturepath);
3823                 for(u32 j=0; j<dirlist.size(); j++){
3824                         if(dirlist[j].dir) // Ignode dirs
3825                                 continue;
3826                         std::string tname = dirlist[j].name;
3827                         // if name contains illegal characters, ignore the texture
3828                         if(!string_allowed(tname, TEXTURENAME_ALLOWED_CHARS)){
3829                                 errorstream<<"Server: ignoring illegal texture name: \""
3830                                                 <<tname<<"\""<<std::endl;
3831                                 continue;
3832                         }
3833                         std::string tpath = texturepath + DIR_DELIM + tname;
3834                         // Read data
3835                         std::ifstream fis(tpath.c_str(), std::ios_base::binary);
3836                         if(fis.good() == false){
3837                                 errorstream<<"Server::PrepareTextures(): Could not open \""
3838                                                 <<tname<<"\" for reading"<<std::endl;
3839                                 continue;
3840                         }
3841                         std::ostringstream tmp_os(std::ios_base::binary);
3842                         bool bad = false;
3843                         for(;;){
3844                                 char buf[1024];
3845                                 fis.read(buf, 1024);
3846                                 std::streamsize len = fis.gcount();
3847                                 tmp_os.write(buf, len);
3848                                 if(fis.eof())
3849                                         break;
3850                                 if(!fis.good()){
3851                                         bad = true;
3852                                         break;
3853                                 }
3854                         }
3855                         if(bad){
3856                                 errorstream<<"Server::PrepareTextures(): Failed to read \""
3857                                                 <<tname<<"\""<<std::endl;
3858                                 continue;
3859                         }
3860                         if(tmp_os.str().length() == 0){
3861                                 errorstream<<"Server::PrepareTextures(): Empty file \""
3862                                                 <<tpath<<"\""<<std::endl;
3863                                 continue;
3864                         }
3865
3866                         SHA1 sha1;
3867                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
3868
3869                         unsigned char *digest = sha1.getDigest();
3870                         std::string digest_string = base64_encode(digest, 20);
3871
3872                         free(digest);
3873
3874                         // Put in list
3875                         this->m_Textures[tname] = TextureInformation(tpath,digest_string);
3876                         verbosestream<<"Server: sha1 for "<<tname<<"\tis "<<std::endl;
3877                 }
3878         }
3879 }
3880
3881 struct SendableTextureAnnouncement
3882         {
3883                 std::string name;
3884                 std::string sha1_digest;
3885
3886                 SendableTextureAnnouncement(const std::string name_="",
3887                                 const std::string sha1_digest_=""):
3888                         name(name_),
3889                         sha1_digest(sha1_digest_)
3890                 {
3891                 }
3892         };
3893
3894 void Server::SendTextureAnnouncement(u16 peer_id){
3895         DSTACK(__FUNCTION_NAME);
3896
3897         verbosestream<<"Server: Announcing textures to id("<<peer_id<<")"
3898                         <<std::endl;
3899
3900         core::list<SendableTextureAnnouncement> texture_announcements;
3901
3902         for (std::map<std::string,TextureInformation>::iterator i = m_Textures.begin();i != m_Textures.end(); i++ ) {
3903
3904                 // Put in list
3905                 texture_announcements.push_back(
3906                                 SendableTextureAnnouncement(i->first, i->second.sha1_digest));
3907         }
3908
3909         //send announcements
3910
3911         /*
3912                 u16 command
3913                 u32 number of textures
3914                 for each texture {
3915                         u16 length of name
3916                         string name
3917                         u16 length of digest string
3918                         string sha1_digest
3919                 }
3920         */
3921         std::ostringstream os(std::ios_base::binary);
3922
3923         writeU16(os,    TOCLIENT_ANNOUNCE_TEXTURES);
3924         writeU16(os, texture_announcements.size());
3925
3926         for(core::list<SendableTextureAnnouncement>::Iterator
3927                         j = texture_announcements.begin();
3928                         j != texture_announcements.end(); j++){
3929                 os<<serializeString(j->name);
3930                 os<<serializeString(j->sha1_digest);
3931         }
3932
3933         // Make data buffer
3934         std::string s = os.str();
3935         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3936
3937         // Send as reliable
3938         m_con.Send(peer_id, 0, data, true);
3939
3940 }
3941
3942 struct SendableTexture
3943 {
3944         std::string name;
3945         std::string path;
3946         std::string data;
3947
3948         SendableTexture(const std::string &name_="", const std::string path_="",
3949                         const std::string &data_=""):
3950                 name(name_),
3951                 path(path_),
3952                 data(data_)
3953         {}
3954 };
3955
3956 void Server::SendTexturesRequested(u16 peer_id,core::list<TextureRequest> tosend) {
3957         DSTACK(__FUNCTION_NAME);
3958
3959         verbosestream<<"Server::SendTexturesRequested(): "
3960                         <<"Sending textures to client"<<std::endl;
3961
3962         /* Read textures */
3963
3964         // Put 5kB in one bunch (this is not accurate)
3965         u32 bytes_per_bunch = 5000;
3966
3967         core::array< core::list<SendableTexture> > texture_bunches;
3968         texture_bunches.push_back(core::list<SendableTexture>());
3969
3970         u32 texture_size_bunch_total = 0;
3971
3972         for(core::list<TextureRequest>::Iterator i = tosend.begin(); i != tosend.end(); i++) {
3973                 if(m_Textures.find(i->name) == m_Textures.end()){
3974                         errorstream<<"Server::SendTexturesRequested(): Client asked for "
3975                                         <<"unknown texture \""<<(i->name)<<"\""<<std::endl;
3976                         continue;
3977                 }
3978
3979                 //TODO get path + name
3980                 std::string tpath = m_Textures[(*i).name].path;
3981
3982                 // Read data
3983                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
3984                 if(fis.good() == false){
3985                         errorstream<<"Server::SendTexturesRequested(): Could not open \""
3986                                         <<tpath<<"\" for reading"<<std::endl;
3987                         continue;
3988                 }
3989                 std::ostringstream tmp_os(std::ios_base::binary);
3990                 bool bad = false;
3991                 for(;;){
3992                         char buf[1024];
3993                         fis.read(buf, 1024);
3994                         std::streamsize len = fis.gcount();
3995                         tmp_os.write(buf, len);
3996                         texture_size_bunch_total += len;
3997                         if(fis.eof())
3998                                 break;
3999                         if(!fis.good()){
4000                                 bad = true;
4001                                 break;
4002                         }
4003                 }
4004                 if(bad){
4005                         errorstream<<"Server::SendTexturesRequested(): Failed to read \""
4006                                         <<(*i).name<<"\""<<std::endl;
4007                         continue;
4008                 }
4009                 /*infostream<<"Server::SendTexturesRequested(): Loaded \""
4010                                 <<tname<<"\""<<std::endl;*/
4011                 // Put in list
4012                 texture_bunches[texture_bunches.size()-1].push_back(
4013                                 SendableTexture((*i).name, tpath, tmp_os.str()));
4014
4015                 // Start next bunch if got enough data
4016                 if(texture_size_bunch_total >= bytes_per_bunch){
4017                         texture_bunches.push_back(core::list<SendableTexture>());
4018                         texture_size_bunch_total = 0;
4019                 }
4020
4021         }
4022
4023         /* Create and send packets */
4024
4025                 u32 num_bunches = texture_bunches.size();
4026                 for(u32 i=0; i<num_bunches; i++)
4027                 {
4028                         /*
4029                                 u16 command
4030                                 u16 total number of texture bunches
4031                                 u16 index of this bunch
4032                                 u32 number of textures in this bunch
4033                                 for each texture {
4034                                         u16 length of name
4035                                         string name
4036                                         u32 length of data
4037                                         data
4038                                 }
4039                         */
4040                         std::ostringstream os(std::ios_base::binary);
4041
4042                         writeU16(os, TOCLIENT_TEXTURES);
4043                         writeU16(os, num_bunches);
4044                         writeU16(os, i);
4045                         writeU32(os, texture_bunches[i].size());
4046
4047                         for(core::list<SendableTexture>::Iterator
4048                                         j = texture_bunches[i].begin();
4049                                         j != texture_bunches[i].end(); j++){
4050                                 os<<serializeString(j->name);
4051                                 os<<serializeLongString(j->data);
4052                         }
4053
4054                         // Make data buffer
4055                         std::string s = os.str();
4056                         verbosestream<<"Server::SendTexturesRequested(): bunch "
4057                                         <<i<<"/"<<num_bunches
4058                                         <<" textures="<<texture_bunches[i].size()
4059                                         <<" size=" <<s.size()<<std::endl;
4060                         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4061                         // Send as reliable
4062                         m_con.Send(peer_id, 0, data, true);
4063                 }
4064
4065
4066 }
4067
4068 /*
4069         Something random
4070 */
4071
4072 void Server::DiePlayer(Player *player)
4073 {
4074         ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
4075
4076         infostream<<"Server::DiePlayer(): Player "
4077                         <<player->getName()<<" dies"<<std::endl;
4078         
4079         srp->setHP(0);
4080         
4081         // Trigger scripted stuff
4082         scriptapi_on_dieplayer(m_lua, srp);
4083         
4084         // Handle players that are not connected
4085         if(player->peer_id == PEER_ID_INEXISTENT){
4086                 RespawnPlayer(player);
4087                 return;
4088         }
4089
4090         SendPlayerHP(player);
4091         SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
4092 }
4093
4094 void Server::RespawnPlayer(Player *player)
4095 {
4096         ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
4097         srp->setHP(20);
4098         bool repositioned = scriptapi_on_respawnplayer(m_lua, srp);
4099         if(!repositioned){
4100                 v3f pos = findSpawnPos(m_env->getServerMap());
4101                 player->setPosition(pos);
4102                 srp->m_last_good_position = pos;
4103                 srp->m_last_good_position_age = 0;
4104         }
4105         SendMovePlayer(player);
4106         SendPlayerHP(player);
4107 }
4108
4109 void Server::UpdateCrafting(u16 peer_id)
4110 {
4111         DSTACK(__FUNCTION_NAME);
4112         
4113         Player* player = m_env->getPlayer(peer_id);
4114         assert(player);
4115
4116         // Get a preview for crafting
4117         ItemStack preview;
4118         // No crafting in creative mode
4119         if(g_settings->getBool("creative_mode") == false)
4120                 getCraftingResult(&player->inventory, preview, false, this);
4121
4122         // Put the new preview in
4123         InventoryList *plist = player->inventory.getList("craftpreview");
4124         assert(plist);
4125         assert(plist->getSize() >= 1);
4126         plist->changeItem(0, preview);
4127 }
4128
4129 RemoteClient* Server::getClient(u16 peer_id)
4130 {
4131         DSTACK(__FUNCTION_NAME);
4132         //JMutexAutoLock lock(m_con_mutex);
4133         core::map<u16, RemoteClient*>::Node *n;
4134         n = m_clients.find(peer_id);
4135         // A client should exist for all peers
4136         assert(n != NULL);
4137         return n->getValue();
4138 }
4139
4140 std::wstring Server::getStatusString()
4141 {
4142         std::wostringstream os(std::ios_base::binary);
4143         os<<L"# Server: ";
4144         // Version
4145         os<<L"version="<<narrow_to_wide(VERSION_STRING);
4146         // Uptime
4147         os<<L", uptime="<<m_uptime.get();
4148         // Information about clients
4149         os<<L", clients={";
4150         for(core::map<u16, RemoteClient*>::Iterator
4151                 i = m_clients.getIterator();
4152                 i.atEnd() == false; i++)
4153         {
4154                 // Get client and check that it is valid
4155                 RemoteClient *client = i.getNode()->getValue();
4156                 assert(client->peer_id == i.getNode()->getKey());
4157                 if(client->serialization_version == SER_FMT_VER_INVALID)
4158                         continue;
4159                 // Get player
4160                 Player *player = m_env->getPlayer(client->peer_id);
4161                 // Get name of player
4162                 std::wstring name = L"unknown";
4163                 if(player != NULL)
4164                         name = narrow_to_wide(player->getName());
4165                 // Add name to information string
4166                 os<<name<<L",";
4167         }
4168         os<<L"}";
4169         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
4170                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
4171         if(g_settings->get("motd") != "")
4172                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
4173         return os.str();
4174 }
4175
4176 u64 Server::getPlayerAuthPrivs(const std::string &name)
4177 {
4178         try{
4179                 return m_authmanager.getPrivs(name);
4180         }
4181         catch(AuthNotFoundException &e)
4182         {
4183                 dstream<<"WARNING: Auth not found for "<<name<<std::endl;
4184                 return 0;
4185         }
4186 }
4187
4188 void Server::setPlayerAuthPrivs(const std::string &name, u64 privs)
4189 {
4190         try{
4191                 return m_authmanager.setPrivs(name, privs);
4192         }
4193         catch(AuthNotFoundException &e)
4194         {
4195                 dstream<<"WARNING: Auth not found for "<<name<<std::endl;
4196         }
4197 }
4198
4199 u64 Server::getPlayerEffectivePrivs(const std::string &name)
4200 {
4201         // Local player gets all privileges regardless of
4202         // what's set on their account.
4203         if(m_simple_singleplayer_mode)
4204                 return PRIV_ALL;
4205         if(name == g_settings->get("name"))
4206                 return PRIV_ALL;
4207         return getPlayerAuthPrivs(name);
4208 }
4209
4210 void Server::setPlayerPassword(const std::string &name, const std::wstring &password)
4211 {
4212         // Add player to auth manager
4213         if(m_authmanager.exists(name) == false)
4214         {
4215                 infostream<<"Server: adding player "<<name
4216                                 <<" to auth manager"<<std::endl;
4217                 m_authmanager.add(name);
4218                 m_authmanager.setPrivs(name,
4219                         stringToPrivs(g_settings->get("default_privs")));
4220         }
4221         // Change password and save
4222         m_authmanager.setPassword(name, translatePassword(name, password));
4223         m_authmanager.save();
4224 }
4225
4226 // Saves g_settings to configpath given at initialization
4227 void Server::saveConfig()
4228 {
4229         if(m_path_config != "")
4230                 g_settings->updateConfigFile(m_path_config.c_str());
4231 }
4232
4233 void Server::notifyPlayer(const char *name, const std::wstring msg)
4234 {
4235         Player *player = m_env->getPlayer(name);
4236         if(!player)
4237                 return;
4238         SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
4239 }
4240
4241 void Server::notifyPlayers(const std::wstring msg)
4242 {
4243         BroadcastChatMessage(msg);
4244 }
4245
4246 void Server::queueBlockEmerge(v3s16 blockpos, bool allow_generate)
4247 {
4248         u8 flags = 0;
4249         if(!allow_generate)
4250                 flags |= BLOCK_EMERGE_FLAG_FROMDISK;
4251         m_emerge_queue.addBlock(PEER_ID_INEXISTENT, blockpos, flags);
4252 }
4253
4254 // IGameDef interface
4255 // Under envlock
4256 IItemDefManager* Server::getItemDefManager()
4257 {
4258         return m_itemdef;
4259 }
4260 INodeDefManager* Server::getNodeDefManager()
4261 {
4262         return m_nodedef;
4263 }
4264 ICraftDefManager* Server::getCraftDefManager()
4265 {
4266         return m_craftdef;
4267 }
4268 ITextureSource* Server::getTextureSource()
4269 {
4270         return NULL;
4271 }
4272 u16 Server::allocateUnknownNodeId(const std::string &name)
4273 {
4274         return m_nodedef->allocateDummy(name);
4275 }
4276 ISoundManager* Server::getSoundManager()
4277 {
4278         return &dummySoundManager;
4279 }
4280 MtEventManager* Server::getEventManager()
4281 {
4282         return m_event;
4283 }
4284
4285 IWritableItemDefManager* Server::getWritableItemDefManager()
4286 {
4287         return m_itemdef;
4288 }
4289 IWritableNodeDefManager* Server::getWritableNodeDefManager()
4290 {
4291         return m_nodedef;
4292 }
4293 IWritableCraftDefManager* Server::getWritableCraftDefManager()
4294 {
4295         return m_craftdef;
4296 }
4297
4298 const ModSpec* Server::getModSpec(const std::string &modname)
4299 {
4300         for(core::list<ModSpec>::Iterator i = m_mods.begin();
4301                         i != m_mods.end(); i++){
4302                 const ModSpec &mod = *i;
4303                 if(mod.name == modname)
4304                         return &mod;
4305         }
4306         return NULL;
4307 }
4308
4309 v3f findSpawnPos(ServerMap &map)
4310 {
4311         //return v3f(50,50,50)*BS;
4312
4313         v3s16 nodepos;
4314         
4315 #if 0
4316         nodepos = v2s16(0,0);
4317         groundheight = 20;
4318 #endif
4319
4320 #if 1
4321         // Try to find a good place a few times
4322         for(s32 i=0; i<1000; i++)
4323         {
4324                 s32 range = 1 + i;
4325                 // We're going to try to throw the player to this position
4326                 v2s16 nodepos2d = v2s16(-range + (myrand()%(range*2)),
4327                                 -range + (myrand()%(range*2)));
4328                 //v2s16 sectorpos = getNodeSectorPos(nodepos2d);
4329                 // Get ground height at point (fallbacks to heightmap function)
4330                 s16 groundheight = map.findGroundLevel(nodepos2d);
4331                 // Don't go underwater
4332                 if(groundheight < WATER_LEVEL)
4333                 {
4334                         //infostream<<"-> Underwater"<<std::endl;
4335                         continue;
4336                 }
4337                 // Don't go to high places
4338                 if(groundheight > WATER_LEVEL + 4)
4339                 {
4340                         //infostream<<"-> Underwater"<<std::endl;
4341                         continue;
4342                 }
4343                 
4344                 nodepos = v3s16(nodepos2d.X, groundheight-2, nodepos2d.Y);
4345                 bool is_good = false;
4346                 s32 air_count = 0;
4347                 for(s32 i=0; i<10; i++){
4348                         v3s16 blockpos = getNodeBlockPos(nodepos);
4349                         map.emergeBlock(blockpos, true);
4350                         MapNode n = map.getNodeNoEx(nodepos);
4351                         if(n.getContent() == CONTENT_AIR){
4352                                 air_count++;
4353                                 if(air_count >= 2){
4354                                         is_good = true;
4355                                         nodepos.Y -= 1;
4356                                         break;
4357                                 }
4358                         }
4359                         nodepos.Y++;
4360                 }
4361                 if(is_good){
4362                         // Found a good place
4363                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
4364                         break;
4365                 }
4366         }
4367 #endif
4368         
4369         return intToFloat(nodepos, BS);
4370 }
4371
4372 ServerRemotePlayer *Server::emergePlayer(const char *name, u16 peer_id)
4373 {
4374         /*
4375                 Try to get an existing player
4376         */
4377         ServerRemotePlayer *player =
4378                         static_cast<ServerRemotePlayer*>(m_env->getPlayer(name));
4379         if(player != NULL)
4380         {
4381                 // If player is already connected, cancel
4382                 if(player->peer_id != 0)
4383                 {
4384                         infostream<<"emergePlayer(): Player already connected"<<std::endl;
4385                         return NULL;
4386                 }
4387
4388                 // Got one.
4389                 player->peer_id = peer_id;
4390                 
4391                 // Re-add player to environment
4392                 if(player->m_removed)
4393                 {
4394                         player->m_removed = false;
4395                         player->setId(0);
4396                         m_env->addActiveObject(player);
4397                 }
4398
4399                 // Reset inventory to creative if in creative mode
4400                 if(g_settings->getBool("creative_mode"))
4401                 {
4402                         // Warning: double code below
4403                         // Backup actual inventory
4404                         player->inventory_backup = new Inventory(m_itemdef);
4405                         *(player->inventory_backup) = player->inventory;
4406                         // Set creative inventory
4407                         player->resetInventory();
4408                         scriptapi_get_creative_inventory(m_lua, player);
4409                 }
4410
4411                 return player;
4412         }
4413
4414         /*
4415                 If player with the wanted peer_id already exists, cancel.
4416         */
4417         if(m_env->getPlayer(peer_id) != NULL)
4418         {
4419                 infostream<<"emergePlayer(): Player with wrong name but same"
4420                                 " peer_id already exists"<<std::endl;
4421                 return NULL;
4422         }
4423         
4424         /*
4425                 Create a new player
4426         */
4427         {
4428                 /* Set player position */
4429                 
4430                 infostream<<"Server: Finding spawn place for player \""
4431                                 <<name<<"\""<<std::endl;
4432
4433                 v3f pos = findSpawnPos(m_env->getServerMap());
4434
4435                 player = new ServerRemotePlayer(m_env, pos, peer_id, name);
4436                 ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
4437
4438                 /* Add player to environment */
4439                 m_env->addPlayer(player);
4440                 m_env->addActiveObject(srp);
4441
4442                 /* Run scripts */
4443                 scriptapi_on_newplayer(m_lua, srp);
4444
4445                 /* Add stuff to inventory */
4446                 if(g_settings->getBool("creative_mode"))
4447                 {
4448                         // Warning: double code above
4449                         // Backup actual inventory
4450                         player->inventory_backup = new Inventory(m_itemdef);
4451                         *(player->inventory_backup) = player->inventory;
4452                         // Set creative inventory
4453                         player->resetInventory();
4454                         scriptapi_get_creative_inventory(m_lua, player);
4455                 }
4456
4457                 return player;
4458                 
4459         } // create new player
4460 }
4461
4462 void Server::handlePeerChange(PeerChange &c)
4463 {
4464         JMutexAutoLock envlock(m_env_mutex);
4465         JMutexAutoLock conlock(m_con_mutex);
4466         
4467         if(c.type == PEER_ADDED)
4468         {
4469                 /*
4470                         Add
4471                 */
4472
4473                 // Error check
4474                 core::map<u16, RemoteClient*>::Node *n;
4475                 n = m_clients.find(c.peer_id);
4476                 // The client shouldn't already exist
4477                 assert(n == NULL);
4478
4479                 // Create client
4480                 RemoteClient *client = new RemoteClient();
4481                 client->peer_id = c.peer_id;
4482                 m_clients.insert(client->peer_id, client);
4483
4484         } // PEER_ADDED
4485         else if(c.type == PEER_REMOVED)
4486         {
4487                 /*
4488                         Delete
4489                 */
4490
4491                 // Error check
4492                 core::map<u16, RemoteClient*>::Node *n;
4493                 n = m_clients.find(c.peer_id);
4494                 // The client should exist
4495                 assert(n != NULL);
4496                 
4497                 /*
4498                         Mark objects to be not known by the client
4499                 */
4500                 RemoteClient *client = n->getValue();
4501                 // Handle objects
4502                 for(core::map<u16, bool>::Iterator
4503                                 i = client->m_known_objects.getIterator();
4504                                 i.atEnd()==false; i++)
4505                 {
4506                         // Get object
4507                         u16 id = i.getNode()->getKey();
4508                         ServerActiveObject* obj = m_env->getActiveObject(id);
4509                         
4510                         if(obj && obj->m_known_by_count > 0)
4511                                 obj->m_known_by_count--;
4512                 }
4513
4514                 ServerRemotePlayer* player =
4515                                 static_cast<ServerRemotePlayer*>(m_env->getPlayer(c.peer_id));
4516
4517                 // Collect information about leaving in chat
4518                 std::wstring message;
4519                 {
4520                         if(player != NULL)
4521                         {
4522                                 std::wstring name = narrow_to_wide(player->getName());
4523                                 message += L"*** ";
4524                                 message += name;
4525                                 message += L" left game";
4526                                 if(c.timeout)
4527                                         message += L" (timed out)";
4528                         }
4529                 }
4530                 
4531                 // Remove from environment
4532                 if(player != NULL)
4533                         player->m_removed = true;
4534                 
4535                 // Set player client disconnected
4536                 if(player != NULL)
4537                         player->peer_id = 0;
4538         
4539                 /*
4540                         Print out action
4541                 */
4542                 {
4543                         if(player != NULL)
4544                         {
4545                                 std::ostringstream os(std::ios_base::binary);
4546                                 for(core::map<u16, RemoteClient*>::Iterator
4547                                         i = m_clients.getIterator();
4548                                         i.atEnd() == false; i++)
4549                                 {
4550                                         RemoteClient *client = i.getNode()->getValue();
4551                                         assert(client->peer_id == i.getNode()->getKey());
4552                                         if(client->serialization_version == SER_FMT_VER_INVALID)
4553                                                 continue;
4554                                         // Get player
4555                                         Player *player = m_env->getPlayer(client->peer_id);
4556                                         if(!player)
4557                                                 continue;
4558                                         // Get name of player
4559                                         os<<player->getName()<<" ";
4560                                 }
4561
4562                                 actionstream<<player->getName()<<" "
4563                                                 <<(c.timeout?"times out.":"leaves game.")
4564                                                 <<" List of players: "
4565                                                 <<os.str()<<std::endl;
4566                         }
4567                 }
4568                 
4569                 // Delete client
4570                 delete m_clients[c.peer_id];
4571                 m_clients.remove(c.peer_id);
4572
4573                 // Send player info to all remaining clients
4574                 //SendPlayerInfos();
4575                 
4576                 // Send leave chat message to all remaining clients
4577                 if(message.length() != 0)
4578                         BroadcastChatMessage(message);
4579                 
4580         } // PEER_REMOVED
4581         else
4582         {
4583                 assert(0);
4584         }
4585 }
4586
4587 void Server::handlePeerChanges()
4588 {
4589         while(m_peer_change_queue.size() > 0)
4590         {
4591                 PeerChange c = m_peer_change_queue.pop_front();
4592
4593                 verbosestream<<"Server: Handling peer change: "
4594                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
4595                                 <<std::endl;
4596
4597                 handlePeerChange(c);
4598         }
4599 }
4600
4601 u64 Server::getPlayerPrivs(Player *player)
4602 {
4603         if(player==NULL)
4604                 return 0;
4605         std::string playername = player->getName();
4606         return getPlayerEffectivePrivs(playername);
4607 }
4608
4609 void dedicated_server_loop(Server &server, bool &kill)
4610 {
4611         DSTACK(__FUNCTION_NAME);
4612         
4613         verbosestream<<"dedicated_server_loop()"<<std::endl;
4614
4615         IntervalLimiter m_profiler_interval;
4616
4617         for(;;)
4618         {
4619                 float steplen = g_settings->getFloat("dedicated_server_step");
4620                 // This is kind of a hack but can be done like this
4621                 // because server.step() is very light
4622                 {
4623                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
4624                         sleep_ms((int)(steplen*1000.0));
4625                 }
4626                 server.step(steplen);
4627
4628                 if(server.getShutdownRequested() || kill)
4629                 {
4630                         infostream<<"Dedicated server quitting"<<std::endl;
4631                         break;
4632                 }
4633
4634                 /*
4635                         Profiler
4636                 */
4637                 float profiler_print_interval =
4638                                 g_settings->getFloat("profiler_print_interval");
4639                 if(profiler_print_interval != 0)
4640                 {
4641                         if(m_profiler_interval.step(steplen, profiler_print_interval))
4642                         {
4643                                 infostream<<"Profiler:"<<std::endl;
4644                                 g_profiler->print(infostream);
4645                                 g_profiler->clear();
4646                         }
4647                 }
4648         }
4649 }
4650
4651