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