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