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