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