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