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