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