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