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