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