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