]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Implement search tab and version picker
[dragonfireclient.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "clientserver.h"
25 #include "ban.h"
26 #include "environment.h"
27 #include "map.h"
28 #include "jthread/jmutexautolock.h"
29 #include "main.h"
30 #include "constants.h"
31 #include "voxel.h"
32 #include "config.h"
33 #include "version.h"
34 #include "filesys.h"
35 #include "mapblock.h"
36 #include "serverobject.h"
37 #include "genericobject.h"
38 #include "settings.h"
39 #include "profiler.h"
40 #include "log.h"
41 #include "scripting_game.h"
42 #include "nodedef.h"
43 #include "itemdef.h"
44 #include "craftdef.h"
45 #include "emerge.h"
46 #include "mapgen.h"
47 #include "biome.h"
48 #include "content_mapnode.h"
49 #include "content_nodemeta.h"
50 #include "content_abm.h"
51 #include "content_sao.h"
52 #include "mods.h"
53 #include "sha1.h"
54 #include "base64.h"
55 #include "tool.h"
56 #include "sound.h" // dummySoundManager
57 #include "event_manager.h"
58 #include "hex.h"
59 #include "serverlist.h"
60 #include "util/string.h"
61 #include "util/pointedthing.h"
62 #include "util/mathconstants.h"
63 #include "rollback.h"
64 #include "util/serialize.h"
65 #include "util/thread.h"
66 #include "defaultsettings.h"
67
68 class ClientNotFoundException : public BaseException
69 {
70 public:
71         ClientNotFoundException(const char *s):
72                 BaseException(s)
73         {}
74 };
75
76 class ServerThread : public SimpleThread
77 {
78         Server *m_server;
79
80 public:
81
82         ServerThread(Server *server):
83                 SimpleThread(),
84                 m_server(server)
85         {
86         }
87
88         void * Thread();
89 };
90
91 void * ServerThread::Thread()
92 {
93         ThreadStarted();
94
95         log_register_thread("ServerThread");
96
97         DSTACK(__FUNCTION_NAME);
98
99         BEGIN_DEBUG_EXCEPTION_HANDLER
100
101         while(getRun())
102         {
103                 try{
104                         //TimeTaker timer("AsyncRunStep() + Receive()");
105
106                         {
107                                 //TimeTaker timer("AsyncRunStep()");
108                                 m_server->AsyncRunStep();
109                         }
110
111                         //infostream<<"Running m_server->Receive()"<<std::endl;
112                         m_server->Receive();
113                 }
114                 catch(con::NoIncomingDataException &e)
115                 {
116                 }
117                 catch(con::PeerNotFoundException &e)
118                 {
119                         infostream<<"Server: PeerNotFoundException"<<std::endl;
120                 }
121                 catch(ClientNotFoundException &e)
122                 {
123                 }
124                 catch(con::ConnectionBindFailed &e)
125                 {
126                         m_server->setAsyncFatalError(e.what());
127                 }
128                 catch(LuaError &e)
129                 {
130                         m_server->setAsyncFatalError(e.what());
131                 }
132         }
133
134         END_DEBUG_EXCEPTION_HANDLER(errorstream)
135
136         return NULL;
137 }
138
139 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
140 {
141         if(pos_exists) *pos_exists = false;
142         switch(type){
143         case SSP_LOCAL:
144                 return v3f(0,0,0);
145         case SSP_POSITIONAL:
146                 if(pos_exists) *pos_exists = true;
147                 return pos;
148         case SSP_OBJECT: {
149                 if(object == 0)
150                         return v3f(0,0,0);
151                 ServerActiveObject *sao = env->getActiveObject(object);
152                 if(!sao)
153                         return v3f(0,0,0);
154                 if(pos_exists) *pos_exists = true;
155                 return sao->getBasePosition(); }
156         }
157         return v3f(0,0,0);
158 }
159
160 void RemoteClient::GetNextBlocks(Server *server, float dtime,
161                 std::vector<PrioritySortedBlockTransfer> &dest)
162 {
163         DSTACK(__FUNCTION_NAME);
164
165         /*u32 timer_result;
166         TimeTaker timer("RemoteClient::GetNextBlocks", &timer_result);*/
167
168         // Increment timers
169         m_nothing_to_send_pause_timer -= dtime;
170         m_nearest_unsent_reset_timer += dtime;
171
172         if(m_nothing_to_send_pause_timer >= 0)
173                 return;
174
175         Player *player = server->m_env->getPlayer(peer_id);
176         // This can happen sometimes; clients and players are not in perfect sync.
177         if(player == NULL)
178                 return;
179
180         // Won't send anything if already sending
181         if(m_blocks_sending.size() >= g_settings->getU16
182                         ("max_simultaneous_block_sends_per_client"))
183         {
184                 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
185                 return;
186         }
187
188         //TimeTaker timer("RemoteClient::GetNextBlocks");
189
190         v3f playerpos = player->getPosition();
191         v3f playerspeed = player->getSpeed();
192         v3f playerspeeddir(0,0,0);
193         if(playerspeed.getLength() > 1.0*BS)
194                 playerspeeddir = playerspeed / playerspeed.getLength();
195         // Predict to next block
196         v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
197
198         v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
199
200         v3s16 center = getNodeBlockPos(center_nodepos);
201
202         // Camera position and direction
203         v3f camera_pos = player->getEyePosition();
204         v3f camera_dir = v3f(0,0,1);
205         camera_dir.rotateYZBy(player->getPitch());
206         camera_dir.rotateXZBy(player->getYaw());
207
208         /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
209                         <<camera_dir.Z<<")"<<std::endl;*/
210
211         /*
212                 Get the starting value of the block finder radius.
213         */
214
215         if(m_last_center != center)
216         {
217                 m_nearest_unsent_d = 0;
218                 m_last_center = center;
219         }
220
221         /*infostream<<"m_nearest_unsent_reset_timer="
222                         <<m_nearest_unsent_reset_timer<<std::endl;*/
223
224         // Reset periodically to workaround for some bugs or stuff
225         if(m_nearest_unsent_reset_timer > 20.0)
226         {
227                 m_nearest_unsent_reset_timer = 0;
228                 m_nearest_unsent_d = 0;
229                 //infostream<<"Resetting m_nearest_unsent_d for "
230                 //              <<server->getPlayerName(peer_id)<<std::endl;
231         }
232
233         //s16 last_nearest_unsent_d = m_nearest_unsent_d;
234         s16 d_start = m_nearest_unsent_d;
235
236         //infostream<<"d_start="<<d_start<<std::endl;
237
238         u16 max_simul_sends_setting = g_settings->getU16
239                         ("max_simultaneous_block_sends_per_client");
240         u16 max_simul_sends_usually = max_simul_sends_setting;
241
242         /*
243                 Check the time from last addNode/removeNode.
244
245                 Decrease send rate if player is building stuff.
246         */
247         m_time_from_building += dtime;
248         if(m_time_from_building < g_settings->getFloat(
249                                 "full_block_send_enable_min_time_from_building"))
250         {
251                 max_simul_sends_usually
252                         = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
253         }
254
255         /*
256                 Number of blocks sending + number of blocks selected for sending
257         */
258         u32 num_blocks_selected = m_blocks_sending.size();
259
260         /*
261                 next time d will be continued from the d from which the nearest
262                 unsent block was found this time.
263
264                 This is because not necessarily any of the blocks found this
265                 time are actually sent.
266         */
267         s32 new_nearest_unsent_d = -1;
268
269         s16 d_max = g_settings->getS16("max_block_send_distance");
270         s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
271
272         // Don't loop very much at a time
273         s16 max_d_increment_at_time = 2;
274         if(d_max > d_start + max_d_increment_at_time)
275                 d_max = d_start + max_d_increment_at_time;
276         /*if(d_max_gen > d_start+2)
277                 d_max_gen = d_start+2;*/
278
279         //infostream<<"Starting from "<<d_start<<std::endl;
280
281         s32 nearest_emerged_d = -1;
282         s32 nearest_emergefull_d = -1;
283         s32 nearest_sent_d = -1;
284         bool queue_is_full = false;
285
286         s16 d;
287         for(d = d_start; d <= d_max; d++)
288         {
289                 /*errorstream<<"checking d="<<d<<" for "
290                                 <<server->getPlayerName(peer_id)<<std::endl;*/
291                 //infostream<<"RemoteClient::SendBlocks(): d="<<d<<std::endl;
292
293                 /*
294                         If m_nearest_unsent_d was changed by the EmergeThread
295                         (it can change it to 0 through SetBlockNotSent),
296                         update our d to it.
297                         Else update m_nearest_unsent_d
298                 */
299                 /*if(m_nearest_unsent_d != last_nearest_unsent_d)
300                 {
301                         d = m_nearest_unsent_d;
302                         last_nearest_unsent_d = m_nearest_unsent_d;
303                 }*/
304
305                 /*
306                         Get the border/face dot coordinates of a "d-radiused"
307                         box
308                 */
309                 std::list<v3s16> list;
310                 getFacePositions(list, d);
311
312                 std::list<v3s16>::iterator li;
313                 for(li=list.begin(); li!=list.end(); ++li)
314                 {
315                         v3s16 p = *li + center;
316
317                         /*
318                                 Send throttling
319                                 - Don't allow too many simultaneous transfers
320                                 - EXCEPT when the blocks are very close
321
322                                 Also, don't send blocks that are already flying.
323                         */
324
325                         // Start with the usual maximum
326                         u16 max_simul_dynamic = max_simul_sends_usually;
327
328                         // If block is very close, allow full maximum
329                         if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
330                                 max_simul_dynamic = max_simul_sends_setting;
331
332                         // Don't select too many blocks for sending
333                         if(num_blocks_selected >= max_simul_dynamic)
334                         {
335                                 queue_is_full = true;
336                                 goto queue_full_break;
337                         }
338
339                         // Don't send blocks that are currently being transferred
340                         if(m_blocks_sending.find(p) != m_blocks_sending.end())
341                                 continue;
342
343                         /*
344                                 Do not go over-limit
345                         */
346                         if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
347                         || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
348                         || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
349                         || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
350                         || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
351                         || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
352                                 continue;
353
354                         // If this is true, inexistent block will be made from scratch
355                         bool generate = d <= d_max_gen;
356
357                         {
358                                 /*// Limit the generating area vertically to 2/3
359                                 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
360                                         generate = false;*/
361
362                                 // Limit the send area vertically to 1/2
363                                 if(abs(p.Y - center.Y) > d_max / 2)
364                                         continue;
365                         }
366
367 #if 0
368                         /*
369                                 If block is far away, don't generate it unless it is
370                                 near ground level.
371                         */
372                         if(d >= 4)
373                         {
374         #if 1
375                                 // Block center y in nodes
376                                 f32 y = (f32)(p.Y * MAP_BLOCKSIZE + MAP_BLOCKSIZE/2);
377                                 // Don't generate if it's very high or very low
378                                 if(y < -64 || y > 64)
379                                         generate = false;
380         #endif
381         #if 0
382                                 v2s16 p2d_nodes_center(
383                                         MAP_BLOCKSIZE*p.X,
384                                         MAP_BLOCKSIZE*p.Z);
385
386                                 // Get ground height in nodes
387                                 s16 gh = server->m_env->getServerMap().findGroundLevel(
388                                                 p2d_nodes_center);
389
390                                 // If differs a lot, don't generate
391                                 if(fabs(gh - y) > MAP_BLOCKSIZE*2)
392                                         generate = false;
393                                         // Actually, don't even send it
394                                         //continue;
395         #endif
396                         }
397 #endif
398
399                         //infostream<<"d="<<d<<std::endl;
400 #if 1
401                         /*
402                                 Don't generate or send if not in sight
403                                 FIXME This only works if the client uses a small enough
404                                 FOV setting. The default of 72 degrees is fine.
405                         */
406
407                         float camera_fov = (72.0*M_PI/180) * 4./3.;
408                         if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
409                         {
410                                 continue;
411                         }
412 #endif
413                         /*
414                                 Don't send already sent blocks
415                         */
416                         {
417                                 if(m_blocks_sent.find(p) != m_blocks_sent.end())
418                                 {
419                                         continue;
420                                 }
421                         }
422
423                         /*
424                                 Check if map has this block
425                         */
426                         MapBlock *block = server->m_env->getMap().getBlockNoCreateNoEx(p);
427
428                         bool surely_not_found_on_disk = false;
429                         bool block_is_invalid = false;
430                         if(block != NULL)
431                         {
432                                 // Reset usage timer, this block will be of use in the future.
433                                 block->resetUsageTimer();
434
435                                 // Block is dummy if data doesn't exist.
436                                 // It means it has been not found from disk and not generated
437                                 if(block->isDummy())
438                                 {
439                                         surely_not_found_on_disk = true;
440                                 }
441
442                                 // Block is valid if lighting is up-to-date and data exists
443                                 if(block->isValid() == false)
444                                 {
445                                         block_is_invalid = true;
446                                 }
447
448                                 /*if(block->isFullyGenerated() == false)
449                                 {
450                                         block_is_invalid = true;
451                                 }*/
452
453 #if 0
454                                 v2s16 p2d(p.X, p.Z);
455                                 ServerMap *map = (ServerMap*)(&server->m_env->getMap());
456                                 v2s16 chunkpos = map->sector_to_chunk(p2d);
457                                 if(map->chunkNonVolatile(chunkpos) == false)
458                                         block_is_invalid = true;
459 #endif
460                                 if(block->isGenerated() == false)
461                                         block_is_invalid = true;
462 #if 1
463                                 /*
464                                         If block is not close, don't send it unless it is near
465                                         ground level.
466
467                                         Block is near ground level if night-time mesh
468                                         differs from day-time mesh.
469                                 */
470                                 if(d >= 4)
471                                 {
472                                         if(block->getDayNightDiff() == false)
473                                                 continue;
474                                 }
475 #endif
476                         }
477
478                         /*
479                                 If block has been marked to not exist on disk (dummy)
480                                 and generating new ones is not wanted, skip block.
481                         */
482                         if(generate == false && surely_not_found_on_disk == true)
483                         {
484                                 // get next one.
485                                 continue;
486                         }
487
488                         /*
489                                 Add inexistent block to emerge queue.
490                         */
491                         if(block == NULL || surely_not_found_on_disk || block_is_invalid)
492                         {
493                         /*      //TODO: Get value from somewhere
494                                 // Allow only one block in emerge queue
495                                 //if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
496                                 // Allow two blocks in queue per client
497                                 //if(server->m_emerge_queue.peerItemCount(peer_id) < 2)
498                                 u32 max_emerge = 5;
499                                 // Make it more responsive when needing to generate stuff
500                                 if(surely_not_found_on_disk)
501                                         max_emerge = 1;
502                                 if(server->m_emerge_queue.peerItemCount(peer_id) < max_emerge)
503                                 {
504                                         //infostream<<"Adding block to emerge queue"<<std::endl;
505
506                                         // Add it to the emerge queue and trigger the thread
507
508                                         u8 flags = 0;
509                                         if(generate == false)
510                                                 flags |= BLOCK_EMERGE_FLAG_FROMDISK;
511
512                                         server->m_emerge_queue.addBlock(peer_id, p, flags);
513                                         server->m_emergethread.trigger();
514
515                                         if(nearest_emerged_d == -1)
516                                                 nearest_emerged_d = d;
517                                 } else {
518                                         if(nearest_emergefull_d == -1)
519                                                 nearest_emergefull_d = d;
520                                         goto queue_full_break;
521                                 }
522                         */
523
524                                 if (server->m_emerge->enqueueBlockEmerge(peer_id, p, generate)) {
525                                         if (nearest_emerged_d == -1)
526                                                 nearest_emerged_d = d;
527                                 } else {
528                                         if (nearest_emergefull_d == -1)
529                                                 nearest_emergefull_d = d;
530                                         goto queue_full_break;
531                                 }
532                                 
533                                 // get next one.
534                                 continue;
535                         }
536
537                         if(nearest_sent_d == -1)
538                                 nearest_sent_d = d;
539
540                         /*
541                                 Add block to send queue
542                         */
543
544                         /*errorstream<<"sending from d="<<d<<" to "
545                                         <<server->getPlayerName(peer_id)<<std::endl;*/
546
547                         PrioritySortedBlockTransfer q((float)d, p, peer_id);
548
549                         dest.push_back(q);
550
551                         num_blocks_selected += 1;
552                 }
553         }
554 queue_full_break:
555
556         //infostream<<"Stopped at "<<d<<std::endl;
557
558         // If nothing was found for sending and nothing was queued for
559         // emerging, continue next time browsing from here
560         if(nearest_emerged_d != -1){
561                 new_nearest_unsent_d = nearest_emerged_d;
562         } else if(nearest_emergefull_d != -1){
563                 new_nearest_unsent_d = nearest_emergefull_d;
564         } else {
565                 if(d > g_settings->getS16("max_block_send_distance")){
566                         new_nearest_unsent_d = 0;
567                         m_nothing_to_send_pause_timer = 2.0;
568                         /*infostream<<"GetNextBlocks(): d wrapped around for "
569                                         <<server->getPlayerName(peer_id)
570                                         <<"; setting to 0 and pausing"<<std::endl;*/
571                 } else {
572                         if(nearest_sent_d != -1)
573                                 new_nearest_unsent_d = nearest_sent_d;
574                         else
575                                 new_nearest_unsent_d = d;
576                 }
577         }
578
579         if(new_nearest_unsent_d != -1)
580                 m_nearest_unsent_d = new_nearest_unsent_d;
581
582         /*timer_result = timer.stop(true);
583         if(timer_result != 0)
584                 infostream<<"GetNextBlocks timeout: "<<timer_result<<" (!=0)"<<std::endl;*/
585 }
586
587 void RemoteClient::GotBlock(v3s16 p)
588 {
589         if(m_blocks_sending.find(p) != m_blocks_sending.end())
590                 m_blocks_sending.erase(p);
591         else
592         {
593                 /*infostream<<"RemoteClient::GotBlock(): Didn't find in"
594                                 " m_blocks_sending"<<std::endl;*/
595                 m_excess_gotblocks++;
596         }
597         m_blocks_sent.insert(p);
598 }
599
600 void RemoteClient::SentBlock(v3s16 p)
601 {
602         if(m_blocks_sending.find(p) == m_blocks_sending.end())
603                 m_blocks_sending[p] = 0.0;
604         else
605                 infostream<<"RemoteClient::SentBlock(): Sent block"
606                                 " already in m_blocks_sending"<<std::endl;
607 }
608
609 void RemoteClient::SetBlockNotSent(v3s16 p)
610 {
611         m_nearest_unsent_d = 0;
612
613         if(m_blocks_sending.find(p) != m_blocks_sending.end())
614                 m_blocks_sending.erase(p);
615         if(m_blocks_sent.find(p) != m_blocks_sent.end())
616                 m_blocks_sent.erase(p);
617 }
618
619 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
620 {
621         m_nearest_unsent_d = 0;
622
623         for(std::map<v3s16, MapBlock*>::iterator
624                         i = blocks.begin();
625                         i != blocks.end(); ++i)
626         {
627                 v3s16 p = i->first;
628
629                 if(m_blocks_sending.find(p) != m_blocks_sending.end())
630                         m_blocks_sending.erase(p);
631                 if(m_blocks_sent.find(p) != m_blocks_sent.end())
632                         m_blocks_sent.erase(p);
633         }
634 }
635
636 /*
637         Server
638 */
639
640 Server::Server(
641                 const std::string &path_world,
642                 const SubgameSpec &gamespec,
643                 bool simple_singleplayer_mode
644         ):
645         m_path_world(path_world),
646         m_gamespec(gamespec),
647         m_simple_singleplayer_mode(simple_singleplayer_mode),
648         m_async_fatal_error(""),
649         m_env(NULL),
650         m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT,
651               g_settings->getBool("enable_ipv6") && g_settings->getBool("ipv6_server"), this),
652         m_banmanager(NULL),
653         m_rollback(NULL),
654         m_rollback_sink_enabled(true),
655         m_enable_rollback_recording(false),
656         m_emerge(NULL),
657         m_script(NULL),
658         m_itemdef(createItemDefManager()),
659         m_nodedef(createNodeDefManager()),
660         m_craftdef(createCraftDefManager()),
661         m_event(new EventManager()),
662         m_thread(NULL),
663         m_time_of_day_send_timer(0),
664         m_uptime(0),
665         m_shutdown_requested(false),
666         m_ignore_map_edit_events(false),
667         m_ignore_map_edit_events_peer_id(0)
668 {
669         m_liquid_transform_timer = 0.0;
670         m_liquid_transform_every = 1.0;
671         m_print_info_timer = 0.0;
672         m_masterserver_timer = 0.0;
673         m_objectdata_timer = 0.0;
674         m_emergethread_trigger_timer = 0.0;
675         m_savemap_timer = 0.0;
676
677         m_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                 infostream<<"Server: New connection: \""<<playername<<"\" from "
1974                                 <<addr_s<<" (peer_id="<<peer_id<<")"<<std::endl;
1975
1976                 // Get password
1977                 char given_password[PASSWORD_SIZE];
1978                 if(datasize < 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE)
1979                 {
1980                         // old version - assume blank password
1981                         given_password[0] = 0;
1982                 }
1983                 else
1984                 {
1985                         for(u32 i=0; i<PASSWORD_SIZE-1; i++)
1986                         {
1987                                 given_password[i] = data[23+i];
1988                         }
1989                         given_password[PASSWORD_SIZE-1] = 0;
1990                 }
1991
1992                 if(!base64_is_valid(given_password)){
1993                         actionstream<<"Server: "<<playername
1994                                         <<" supplied invalid password hash"<<std::endl;
1995                         DenyAccess(peer_id, L"Invalid password hash");
1996                         return;
1997                 }
1998
1999                 // Enforce user limit.
2000                 // Don't enforce for users that have some admin right
2001                 if(m_clients.size() >= g_settings->getU16("max_users") &&
2002                                 !checkPriv(playername, "server") &&
2003                                 !checkPriv(playername, "ban") &&
2004                                 !checkPriv(playername, "privs") &&
2005                                 !checkPriv(playername, "password") &&
2006                                 playername != g_settings->get("name"))
2007                 {
2008                         actionstream<<"Server: "<<playername<<" tried to join, but there"
2009                                         <<" are already max_users="
2010                                         <<g_settings->getU16("max_users")<<" players."<<std::endl;
2011                         DenyAccess(peer_id, L"Too many users.");
2012                         return;
2013                 }
2014
2015                 std::string checkpwd; // Password hash to check against
2016                 bool has_auth = m_script->getAuth(playername, &checkpwd, NULL);
2017
2018                 // If no authentication info exists for user, create it
2019                 if(!has_auth){
2020                         if(!isSingleplayer() &&
2021                                         g_settings->getBool("disallow_empty_password") &&
2022                                         std::string(given_password) == ""){
2023                                 actionstream<<"Server: "<<playername
2024                                                 <<" supplied empty password"<<std::endl;
2025                                 DenyAccess(peer_id, L"Empty passwords are "
2026                                                 L"disallowed. Set a password and try again.");
2027                                 return;
2028                         }
2029                         std::wstring raw_default_password =
2030                                 narrow_to_wide(g_settings->get("default_password"));
2031                         std::string initial_password =
2032                                 translatePassword(playername, raw_default_password);
2033
2034                         // If default_password is empty, allow any initial password
2035                         if (raw_default_password.length() == 0)
2036                                 initial_password = given_password;
2037
2038                         m_script->createAuth(playername, initial_password);
2039                 }
2040
2041                 has_auth = m_script->getAuth(playername, &checkpwd, NULL);
2042
2043                 if(!has_auth){
2044                         actionstream<<"Server: "<<playername<<" cannot be authenticated"
2045                                         <<" (auth handler does not work?)"<<std::endl;
2046                         DenyAccess(peer_id, L"Not allowed to login");
2047                         return;
2048                 }
2049
2050                 if(given_password != checkpwd){
2051                         actionstream<<"Server: "<<playername<<" supplied wrong password"
2052                                         <<std::endl;
2053                         DenyAccess(peer_id, L"Wrong password");
2054                         return;
2055                 }
2056
2057                 // Get player
2058                 PlayerSAO *playersao = emergePlayer(playername, peer_id);
2059
2060                 // If failed, cancel
2061                 if(playersao == NULL)
2062                 {
2063                         RemotePlayer *player =
2064                                         static_cast<RemotePlayer*>(m_env->getPlayer(playername));
2065                         if(player && player->peer_id != 0){
2066                                 errorstream<<"Server: "<<playername<<": Failed to emerge player"
2067                                                 <<" (player allocated to an another client)"<<std::endl;
2068                                 DenyAccess(peer_id, L"Another client is connected with this "
2069                                                 L"name. If your client closed unexpectedly, try again in "
2070                                                 L"a minute.");
2071                         } else {
2072                                 errorstream<<"Server: "<<playername<<": Failed to emerge player"
2073                                                 <<std::endl;
2074                                 DenyAccess(peer_id, L"Could not allocate player.");
2075                         }
2076                         return;
2077                 }
2078
2079                 /*
2080                         Answer with a TOCLIENT_INIT
2081                 */
2082                 {
2083                         SharedBuffer<u8> reply(2+1+6+8+4);
2084                         writeU16(&reply[0], TOCLIENT_INIT);
2085                         writeU8(&reply[2], deployed);
2086                         writeV3S16(&reply[2+1], floatToInt(playersao->getPlayer()->getPosition()+v3f(0,BS/2,0), BS));
2087                         writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
2088                         writeF1000(&reply[2+1+6+8], g_settings->getFloat("dedicated_server_step"));
2089
2090                         // Send as reliable
2091                         m_con.Send(peer_id, 0, reply, true);
2092                 }
2093
2094                 /*
2095                         Send complete position information
2096                 */
2097                 SendMovePlayer(peer_id);
2098
2099                 return;
2100         }
2101
2102         if(command == TOSERVER_INIT2)
2103         {
2104                 verbosestream<<"Server: Got TOSERVER_INIT2 from "
2105                                 <<peer_id<<std::endl;
2106
2107                 Player *player = m_env->getPlayer(peer_id);
2108                 if(!player){
2109                         verbosestream<<"Server: TOSERVER_INIT2: "
2110                                         <<"Player not found; ignoring."<<std::endl;
2111                         return;
2112                 }
2113
2114                 RemoteClient *client = getClient(peer_id);
2115                 client->serialization_version =
2116                                 getClient(peer_id)->pending_serialization_version;
2117
2118                 /*
2119                         Send some initialization data
2120                 */
2121
2122                 infostream<<"Server: Sending content to "
2123                                 <<getPlayerName(peer_id)<<std::endl;
2124
2125                 // Send player movement settings
2126                 SendMovement(m_con, peer_id);
2127
2128                 // Send item definitions
2129                 SendItemDef(m_con, peer_id, m_itemdef, client->net_proto_version);
2130
2131                 // Send node definitions
2132                 SendNodeDef(m_con, peer_id, m_nodedef, client->net_proto_version);
2133
2134                 // Send media announcement
2135                 sendMediaAnnouncement(peer_id);
2136
2137                 // Send privileges
2138                 SendPlayerPrivileges(peer_id);
2139
2140                 // Send inventory formspec
2141                 SendPlayerInventoryFormspec(peer_id);
2142
2143                 // Send inventory
2144                 UpdateCrafting(peer_id);
2145                 SendInventory(peer_id);
2146
2147                 // Send HP
2148                 if(g_settings->getBool("enable_damage"))
2149                         SendPlayerHP(peer_id);
2150
2151                 // Send Breath
2152                 SendPlayerBreath(peer_id);
2153
2154                 // Send detached inventories
2155                 sendDetachedInventories(peer_id);
2156
2157                 // Show death screen if necessary
2158                 if(player->hp == 0)
2159                         SendDeathscreen(m_con, peer_id, false, v3f(0,0,0));
2160
2161                 // Send time of day
2162                 {
2163                         u16 time = m_env->getTimeOfDay();
2164                         float time_speed = g_settings->getFloat("time_speed");
2165                         SendTimeOfDay(peer_id, time, time_speed);
2166                 }
2167
2168                 // Note things in chat if not in simple singleplayer mode
2169                 if(!m_simple_singleplayer_mode)
2170                 {
2171                         // Send information about server to player in chat
2172                         SendChatMessage(peer_id, getStatusString());
2173
2174                         // Send information about joining in chat
2175                         {
2176                                 std::wstring name = L"unknown";
2177                                 Player *player = m_env->getPlayer(peer_id);
2178                                 if(player != NULL)
2179                                         name = narrow_to_wide(player->getName());
2180
2181                                 std::wstring message;
2182                                 message += L"*** ";
2183                                 message += name;
2184                                 message += L" joined the game.";
2185                                 BroadcastChatMessage(message);
2186                         }
2187                 }
2188
2189                 // Warnings about protocol version can be issued here
2190                 if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION)
2191                 {
2192                         SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT'S "
2193                                         L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!");
2194                 }
2195
2196                 /*
2197                         Print out action
2198                 */
2199                 {
2200                         std::ostringstream os(std::ios_base::binary);
2201                         for(std::map<u16, RemoteClient*>::iterator
2202                                 i = m_clients.begin();
2203                                 i != m_clients.end(); ++i)
2204                         {
2205                                 RemoteClient *client = i->second;
2206                                 assert(client->peer_id == i->first);
2207                                 if(client->serialization_version == SER_FMT_VER_INVALID)
2208                                         continue;
2209                                 // Get player
2210                                 Player *player = m_env->getPlayer(client->peer_id);
2211                                 if(!player)
2212                                         continue;
2213                                 // Get name of player
2214                                 os<<player->getName()<<" ";
2215                         }
2216
2217                         actionstream<<player->getName()<<" ["<<addr_s<<"] "<<"joins game. List of players: "
2218                                         <<os.str()<<std::endl;
2219                 }
2220
2221                 return;
2222         }
2223
2224         if(peer_ser_ver == SER_FMT_VER_INVALID)
2225         {
2226                 infostream<<"Server::ProcessData(): Cancelling: Peer"
2227                                 " serialization format invalid or not initialized."
2228                                 " Skipping incoming command="<<command<<std::endl;
2229                 return;
2230         }
2231
2232         Player *player = m_env->getPlayer(peer_id);
2233         if(player == NULL){
2234                 infostream<<"Server::ProcessData(): Cancelling: "
2235                                 "No player for peer_id="<<peer_id
2236                                 <<std::endl;
2237                 return;
2238         }
2239
2240         PlayerSAO *playersao = player->getPlayerSAO();
2241         if(playersao == NULL){
2242                 infostream<<"Server::ProcessData(): Cancelling: "
2243                                 "No player object for peer_id="<<peer_id
2244                                 <<std::endl;
2245                 return;
2246         }
2247
2248         if(command == TOSERVER_PLAYERPOS)
2249         {
2250                 if(datasize < 2+12+12+4+4)
2251                         return;
2252
2253                 u32 start = 0;
2254                 v3s32 ps = readV3S32(&data[start+2]);
2255                 v3s32 ss = readV3S32(&data[start+2+12]);
2256                 f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0;
2257                 f32 yaw = (f32)readS32(&data[2+12+12+4]) / 100.0;
2258                 u32 keyPressed = 0;
2259                 if(datasize >= 2+12+12+4+4+4)
2260                         keyPressed = (u32)readU32(&data[2+12+12+4+4]);
2261                 v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.);
2262                 v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.);
2263                 pitch = wrapDegrees(pitch);
2264                 yaw = wrapDegrees(yaw);
2265
2266                 player->setPosition(position);
2267                 player->setSpeed(speed);
2268                 player->setPitch(pitch);
2269                 player->setYaw(yaw);
2270                 player->keyPressed=keyPressed;
2271                 player->control.up = (bool)(keyPressed&1);
2272                 player->control.down = (bool)(keyPressed&2);
2273                 player->control.left = (bool)(keyPressed&4);
2274                 player->control.right = (bool)(keyPressed&8);
2275                 player->control.jump = (bool)(keyPressed&16);
2276                 player->control.aux1 = (bool)(keyPressed&32);
2277                 player->control.sneak = (bool)(keyPressed&64);
2278                 player->control.LMB = (bool)(keyPressed&128);
2279                 player->control.RMB = (bool)(keyPressed&256);
2280
2281                 bool cheated = playersao->checkMovementCheat();
2282                 if(cheated){
2283                         // Call callbacks
2284                         m_script->on_cheat(playersao, "moved_too_fast");
2285                 }
2286
2287                 /*infostream<<"Server::ProcessData(): Moved player "<<peer_id<<" to "
2288                                                                                                                         <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
2289                                                                                                                         <<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
2290
2291         }
2292         else if(command == TOSERVER_GOTBLOCKS)
2293         {
2294                 if(datasize < 2+1)
2295                         return;
2296
2297                 /*
2298                         [0] u16 command
2299                         [2] u8 count
2300                         [3] v3s16 pos_0
2301                         [3+6] v3s16 pos_1
2302                         ...
2303                 */
2304
2305                 u16 count = data[2];
2306                 for(u16 i=0; i<count; i++)
2307                 {
2308                         if((s16)datasize < 2+1+(i+1)*6)
2309                                 throw con::InvalidIncomingDataException
2310                                         ("GOTBLOCKS length is too short");
2311                         v3s16 p = readV3S16(&data[2+1+i*6]);
2312                         /*infostream<<"Server: GOTBLOCKS ("
2313                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
2314                         RemoteClient *client = getClient(peer_id);
2315                         client->GotBlock(p);
2316                 }
2317         }
2318         else if(command == TOSERVER_DELETEDBLOCKS)
2319         {
2320                 if(datasize < 2+1)
2321                         return;
2322
2323                 /*
2324                         [0] u16 command
2325                         [2] u8 count
2326                         [3] v3s16 pos_0
2327                         [3+6] v3s16 pos_1
2328                         ...
2329                 */
2330
2331                 u16 count = data[2];
2332                 for(u16 i=0; i<count; i++)
2333                 {
2334                         if((s16)datasize < 2+1+(i+1)*6)
2335                                 throw con::InvalidIncomingDataException
2336                                         ("DELETEDBLOCKS length is too short");
2337                         v3s16 p = readV3S16(&data[2+1+i*6]);
2338                         /*infostream<<"Server: DELETEDBLOCKS ("
2339                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
2340                         RemoteClient *client = getClient(peer_id);
2341                         client->SetBlockNotSent(p);
2342                 }
2343         }
2344         else if(command == TOSERVER_CLICK_OBJECT)
2345         {
2346                 infostream<<"Server: CLICK_OBJECT not supported anymore"<<std::endl;
2347                 return;
2348         }
2349         else if(command == TOSERVER_CLICK_ACTIVEOBJECT)
2350         {
2351                 infostream<<"Server: CLICK_ACTIVEOBJECT not supported anymore"<<std::endl;
2352                 return;
2353         }
2354         else if(command == TOSERVER_GROUND_ACTION)
2355         {
2356                 infostream<<"Server: GROUND_ACTION not supported anymore"<<std::endl;
2357                 return;
2358
2359         }
2360         else if(command == TOSERVER_RELEASE)
2361         {
2362                 infostream<<"Server: RELEASE not supported anymore"<<std::endl;
2363                 return;
2364         }
2365         else if(command == TOSERVER_SIGNTEXT)
2366         {
2367                 infostream<<"Server: SIGNTEXT not supported anymore"
2368                                 <<std::endl;
2369                 return;
2370         }
2371         else if(command == TOSERVER_SIGNNODETEXT)
2372         {
2373                 infostream<<"Server: SIGNNODETEXT not supported anymore"
2374                                 <<std::endl;
2375                 return;
2376         }
2377         else if(command == TOSERVER_INVENTORY_ACTION)
2378         {
2379                 // Strip command and create a stream
2380                 std::string datastring((char*)&data[2], datasize-2);
2381                 verbosestream<<"TOSERVER_INVENTORY_ACTION: data="<<datastring<<std::endl;
2382                 std::istringstream is(datastring, std::ios_base::binary);
2383                 // Create an action
2384                 InventoryAction *a = InventoryAction::deSerialize(is);
2385                 if(a == NULL)
2386                 {
2387                         infostream<<"TOSERVER_INVENTORY_ACTION: "
2388                                         <<"InventoryAction::deSerialize() returned NULL"
2389                                         <<std::endl;
2390                         return;
2391                 }
2392
2393                 // If something goes wrong, this player is to blame
2394                 RollbackScopeActor rollback_scope(m_rollback,
2395                                 std::string("player:")+player->getName());
2396
2397                 /*
2398                         Note: Always set inventory not sent, to repair cases
2399                         where the client made a bad prediction.
2400                 */
2401
2402                 /*
2403                         Handle restrictions and special cases of the move action
2404                 */
2405                 if(a->getType() == IACTION_MOVE)
2406                 {
2407                         IMoveAction *ma = (IMoveAction*)a;
2408
2409                         ma->from_inv.applyCurrentPlayer(player->getName());
2410                         ma->to_inv.applyCurrentPlayer(player->getName());
2411
2412                         setInventoryModified(ma->from_inv);
2413                         setInventoryModified(ma->to_inv);
2414
2415                         bool from_inv_is_current_player =
2416                                 (ma->from_inv.type == InventoryLocation::PLAYER) &&
2417                                 (ma->from_inv.name == player->getName());
2418
2419                         bool to_inv_is_current_player =
2420                                 (ma->to_inv.type == InventoryLocation::PLAYER) &&
2421                                 (ma->to_inv.name == player->getName());
2422
2423                         /*
2424                                 Disable moving items out of craftpreview
2425                         */
2426                         if(ma->from_list == "craftpreview")
2427                         {
2428                                 infostream<<"Ignoring IMoveAction from "
2429                                                 <<(ma->from_inv.dump())<<":"<<ma->from_list
2430                                                 <<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
2431                                                 <<" because src is "<<ma->from_list<<std::endl;
2432                                 delete a;
2433                                 return;
2434                         }
2435
2436                         /*
2437                                 Disable moving items into craftresult and craftpreview
2438                         */
2439                         if(ma->to_list == "craftpreview" || ma->to_list == "craftresult")
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 dst is "<<ma->to_list<<std::endl;
2445                                 delete a;
2446                                 return;
2447                         }
2448
2449                         // Disallow moving items in elsewhere than player's inventory
2450                         // if not allowed to interact
2451                         if(!checkPriv(player->getName(), "interact") &&
2452                                         (!from_inv_is_current_player ||
2453                                         !to_inv_is_current_player))
2454                         {
2455                                 infostream<<"Cannot move outside of player's inventory: "
2456                                                 <<"No interact privilege"<<std::endl;
2457                                 delete a;
2458                                 return;
2459                         }
2460                 }
2461                 /*
2462                         Handle restrictions and special cases of the drop action
2463                 */
2464                 else if(a->getType() == IACTION_DROP)
2465                 {
2466                         IDropAction *da = (IDropAction*)a;
2467
2468                         da->from_inv.applyCurrentPlayer(player->getName());
2469
2470                         setInventoryModified(da->from_inv);
2471
2472                         /*
2473                                 Disable dropping items out of craftpreview
2474                         */
2475                         if(da->from_list == "craftpreview")
2476                         {
2477                                 infostream<<"Ignoring IDropAction from "
2478                                                 <<(da->from_inv.dump())<<":"<<da->from_list
2479                                                 <<" because src is "<<da->from_list<<std::endl;
2480                                 delete a;
2481                                 return;
2482                         }
2483
2484                         // Disallow dropping items if not allowed to interact
2485                         if(!checkPriv(player->getName(), "interact"))
2486                         {
2487                                 delete a;
2488                                 return;
2489                         }
2490                 }
2491                 /*
2492                         Handle restrictions and special cases of the craft action
2493                 */
2494                 else if(a->getType() == IACTION_CRAFT)
2495                 {
2496                         ICraftAction *ca = (ICraftAction*)a;
2497
2498                         ca->craft_inv.applyCurrentPlayer(player->getName());
2499
2500                         setInventoryModified(ca->craft_inv);
2501
2502                         //bool craft_inv_is_current_player =
2503                         //      (ca->craft_inv.type == InventoryLocation::PLAYER) &&
2504                         //      (ca->craft_inv.name == player->getName());
2505
2506                         // Disallow crafting if not allowed to interact
2507                         if(!checkPriv(player->getName(), "interact"))
2508                         {
2509                                 infostream<<"Cannot craft: "
2510                                                 <<"No interact privilege"<<std::endl;
2511                                 delete a;
2512                                 return;
2513                         }
2514                 }
2515
2516                 // Do the action
2517                 a->apply(this, playersao, this);
2518                 // Eat the action
2519                 delete a;
2520         }
2521         else if(command == TOSERVER_CHAT_MESSAGE)
2522         {
2523                 /*
2524                         u16 command
2525                         u16 length
2526                         wstring message
2527                 */
2528                 u8 buf[6];
2529                 std::string datastring((char*)&data[2], datasize-2);
2530                 std::istringstream is(datastring, std::ios_base::binary);
2531
2532                 // Read stuff
2533                 is.read((char*)buf, 2);
2534                 u16 len = readU16(buf);
2535
2536                 std::wstring message;
2537                 for(u16 i=0; i<len; i++)
2538                 {
2539                         is.read((char*)buf, 2);
2540                         message += (wchar_t)readU16(buf);
2541                 }
2542
2543                 // If something goes wrong, this player is to blame
2544                 RollbackScopeActor rollback_scope(m_rollback,
2545                                 std::string("player:")+player->getName());
2546
2547                 // Get player name of this client
2548                 std::wstring name = narrow_to_wide(player->getName());
2549
2550                 // Run script hook
2551                 bool ate = m_script->on_chat_message(player->getName(),
2552                                 wide_to_narrow(message));
2553                 // If script ate the message, don't proceed
2554                 if(ate)
2555                         return;
2556
2557                 // Line to send to players
2558                 std::wstring line;
2559                 // Whether to send to the player that sent the line
2560                 bool send_to_sender = false;
2561                 // Whether to send to other players
2562                 bool send_to_others = false;
2563
2564                 // Commands are implemented in Lua, so only catch invalid
2565                 // commands that were not "eaten" and send an error back
2566                 if(message[0] == L'/')
2567                 {
2568                         message = message.substr(1);
2569                         send_to_sender = true;
2570                         if(message.length() == 0)
2571                                 line += L"-!- Empty command";
2572                         else
2573                                 line += L"-!- Invalid command: " + str_split(message, L' ')[0];
2574                 }
2575                 else
2576                 {
2577                         if(checkPriv(player->getName(), "shout")){
2578                                 line += L"<";
2579                                 line += name;
2580                                 line += L"> ";
2581                                 line += message;
2582                                 send_to_others = true;
2583                         } else {
2584                                 line += L"-!- You don't have permission to shout.";
2585                                 send_to_sender = true;
2586                         }
2587                 }
2588
2589                 if(line != L"")
2590                 {
2591                         if(send_to_others)
2592                                 actionstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
2593
2594                         /*
2595                                 Send the message to clients
2596                         */
2597                         for(std::map<u16, RemoteClient*>::iterator
2598                                 i = m_clients.begin();
2599                                 i != m_clients.end(); ++i)
2600                         {
2601                                 // Get client and check that it is valid
2602                                 RemoteClient *client = i->second;
2603                                 assert(client->peer_id == i->first);
2604                                 if(client->serialization_version == SER_FMT_VER_INVALID)
2605                                         continue;
2606
2607                                 // Filter recipient
2608                                 bool sender_selected = (peer_id == client->peer_id);
2609                                 if(sender_selected == true && send_to_sender == false)
2610                                         continue;
2611                                 if(sender_selected == false && send_to_others == false)
2612                                         continue;
2613
2614                                 SendChatMessage(client->peer_id, line);
2615                         }
2616                 }
2617         }
2618         else if(command == TOSERVER_DAMAGE)
2619         {
2620                 std::string datastring((char*)&data[2], datasize-2);
2621                 std::istringstream is(datastring, std::ios_base::binary);
2622                 u8 damage = readU8(is);
2623
2624                 if(g_settings->getBool("enable_damage"))
2625                 {
2626                         actionstream<<player->getName()<<" damaged by "
2627                                         <<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
2628                                         <<std::endl;
2629
2630                         playersao->setHP(playersao->getHP() - damage);
2631
2632                         if(playersao->getHP() == 0 && playersao->m_hp_not_sent)
2633                                 DiePlayer(peer_id);
2634
2635                         if(playersao->m_hp_not_sent)
2636                                 SendPlayerHP(peer_id);
2637                 }
2638         }
2639         else if(command == TOSERVER_BREATH)
2640         {
2641                 std::string datastring((char*)&data[2], datasize-2);
2642                 std::istringstream is(datastring, std::ios_base::binary);
2643                 u16 breath = readU16(is);
2644                 playersao->setBreath(breath);
2645         }
2646         else if(command == TOSERVER_PASSWORD)
2647         {
2648                 /*
2649                         [0] u16 TOSERVER_PASSWORD
2650                         [2] u8[28] old password
2651                         [30] u8[28] new password
2652                 */
2653
2654                 if(datasize != 2+PASSWORD_SIZE*2)
2655                         return;
2656                 /*char password[PASSWORD_SIZE];
2657                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2658                         password[i] = data[2+i];
2659                 password[PASSWORD_SIZE-1] = 0;*/
2660                 std::string oldpwd;
2661                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2662                 {
2663                         char c = data[2+i];
2664                         if(c == 0)
2665                                 break;
2666                         oldpwd += c;
2667                 }
2668                 std::string newpwd;
2669                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2670                 {
2671                         char c = data[2+PASSWORD_SIZE+i];
2672                         if(c == 0)
2673                                 break;
2674                         newpwd += c;
2675                 }
2676
2677                 if(!base64_is_valid(newpwd)){
2678                         infostream<<"Server: "<<player->getName()<<" supplied invalid password hash"<<std::endl;
2679                         // Wrong old password supplied!!
2680                         SendChatMessage(peer_id, L"Invalid new password hash supplied. Password NOT changed.");
2681                         return;
2682                 }
2683
2684                 infostream<<"Server: Client requests a password change from "
2685                                 <<"'"<<oldpwd<<"' to '"<<newpwd<<"'"<<std::endl;
2686
2687                 std::string playername = player->getName();
2688
2689                 std::string checkpwd;
2690                 m_script->getAuth(playername, &checkpwd, NULL);
2691
2692                 if(oldpwd != checkpwd)
2693                 {
2694                         infostream<<"Server: invalid old password"<<std::endl;
2695                         // Wrong old password supplied!!
2696                         SendChatMessage(peer_id, L"Invalid old password supplied. Password NOT changed.");
2697                         return;
2698                 }
2699
2700                 bool success = m_script->setPassword(playername, newpwd);
2701                 if(success){
2702                         actionstream<<player->getName()<<" changes password"<<std::endl;
2703                         SendChatMessage(peer_id, L"Password change successful.");
2704                 } else {
2705                         actionstream<<player->getName()<<" tries to change password but "
2706                                         <<"it fails"<<std::endl;
2707                         SendChatMessage(peer_id, L"Password change failed or inavailable.");
2708                 }
2709         }
2710         else if(command == TOSERVER_PLAYERITEM)
2711         {
2712                 if (datasize < 2+2)
2713                         return;
2714
2715                 u16 item = readU16(&data[2]);
2716                 playersao->setWieldIndex(item);
2717         }
2718         else if(command == TOSERVER_RESPAWN)
2719         {
2720                 if(player->hp != 0 || !g_settings->getBool("enable_damage"))
2721                         return;
2722
2723                 RespawnPlayer(peer_id);
2724
2725                 actionstream<<player->getName()<<" respawns at "
2726                                 <<PP(player->getPosition()/BS)<<std::endl;
2727
2728                 // ActiveObject is added to environment in AsyncRunStep after
2729                 // the previous addition has been succesfully removed
2730         }
2731         else if(command == TOSERVER_REQUEST_MEDIA) {
2732                 std::string datastring((char*)&data[2], datasize-2);
2733                 std::istringstream is(datastring, std::ios_base::binary);
2734
2735                 std::list<MediaRequest> tosend;
2736                 u16 numfiles = readU16(is);
2737
2738                 infostream<<"Sending "<<numfiles<<" files to "
2739                                 <<getPlayerName(peer_id)<<std::endl;
2740                 verbosestream<<"TOSERVER_REQUEST_MEDIA: "<<std::endl;
2741
2742                 for(int i = 0; i < numfiles; i++) {
2743                         std::string name = deSerializeString(is);
2744                         tosend.push_back(MediaRequest(name));
2745                         verbosestream<<"TOSERVER_REQUEST_MEDIA: requested file "
2746                                         <<name<<std::endl;
2747                 }
2748
2749                 sendRequestedMedia(peer_id, tosend);
2750
2751                 // Now the client should know about everything
2752                 // (definitions and files)
2753                 getClient(peer_id)->definitions_sent = true;
2754         }
2755         else if(command == TOSERVER_RECEIVED_MEDIA) {
2756                 getClient(peer_id)->definitions_sent = true;
2757         }
2758         else if(command == TOSERVER_INTERACT)
2759         {
2760                 std::string datastring((char*)&data[2], datasize-2);
2761                 std::istringstream is(datastring, std::ios_base::binary);
2762
2763                 /*
2764                         [0] u16 command
2765                         [2] u8 action
2766                         [3] u16 item
2767                         [5] u32 length of the next item
2768                         [9] serialized PointedThing
2769                         actions:
2770                         0: start digging (from undersurface) or use
2771                         1: stop digging (all parameters ignored)
2772                         2: digging completed
2773                         3: place block or item (to abovesurface)
2774                         4: use item
2775                 */
2776                 u8 action = readU8(is);
2777                 u16 item_i = readU16(is);
2778                 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
2779                 PointedThing pointed;
2780                 pointed.deSerialize(tmp_is);
2781
2782                 verbosestream<<"TOSERVER_INTERACT: action="<<(int)action<<", item="
2783                                 <<item_i<<", pointed="<<pointed.dump()<<std::endl;
2784
2785                 if(player->hp == 0)
2786                 {
2787                         verbosestream<<"TOSERVER_INTERACT: "<<player->getName()
2788                                 <<" tried to interact, but is dead!"<<std::endl;
2789                         return;
2790                 }
2791
2792                 v3f player_pos = playersao->getLastGoodPosition();
2793
2794                 // Update wielded item
2795                 playersao->setWieldIndex(item_i);
2796
2797                 // Get pointed to node (undefined if not POINTEDTYPE_NODE)
2798                 v3s16 p_under = pointed.node_undersurface;
2799                 v3s16 p_above = pointed.node_abovesurface;
2800
2801                 // Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
2802                 ServerActiveObject *pointed_object = NULL;
2803                 if(pointed.type == POINTEDTHING_OBJECT)
2804                 {
2805                         pointed_object = m_env->getActiveObject(pointed.object_id);
2806                         if(pointed_object == NULL)
2807                         {
2808                                 verbosestream<<"TOSERVER_INTERACT: "
2809                                         "pointed object is NULL"<<std::endl;
2810                                 return;
2811                         }
2812
2813                 }
2814
2815                 v3f pointed_pos_under = player_pos;
2816                 v3f pointed_pos_above = player_pos;
2817                 if(pointed.type == POINTEDTHING_NODE)
2818                 {
2819                         pointed_pos_under = intToFloat(p_under, BS);
2820                         pointed_pos_above = intToFloat(p_above, BS);
2821                 }
2822                 else if(pointed.type == POINTEDTHING_OBJECT)
2823                 {
2824                         pointed_pos_under = pointed_object->getBasePosition();
2825                         pointed_pos_above = pointed_pos_under;
2826                 }
2827
2828                 /*
2829                         Check that target is reasonably close
2830                         (only when digging or placing things)
2831                 */
2832                 if(action == 0 || action == 2 || action == 3)
2833                 {
2834                         float d = player_pos.getDistanceFrom(pointed_pos_under);
2835                         float max_d = BS * 14; // Just some large enough value
2836                         if(d > max_d){
2837                                 actionstream<<"Player "<<player->getName()
2838                                                 <<" tried to access "<<pointed.dump()
2839                                                 <<" from too far: "
2840                                                 <<"d="<<d<<", max_d="<<max_d
2841                                                 <<". ignoring."<<std::endl;
2842                                 // Re-send block to revert change on client-side
2843                                 RemoteClient *client = getClient(peer_id);
2844                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2845                                 client->SetBlockNotSent(blockpos);
2846                                 // Call callbacks
2847                                 m_script->on_cheat(playersao, "interacted_too_far");
2848                                 // Do nothing else
2849                                 return;
2850                         }
2851                 }
2852
2853                 /*
2854                         Make sure the player is allowed to do it
2855                 */
2856                 if(!checkPriv(player->getName(), "interact"))
2857                 {
2858                         actionstream<<player->getName()<<" attempted to interact with "
2859                                         <<pointed.dump()<<" without 'interact' privilege"
2860                                         <<std::endl;
2861                         // Re-send block to revert change on client-side
2862                         RemoteClient *client = getClient(peer_id);
2863                         // Digging completed -> under
2864                         if(action == 2){
2865                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2866                                 client->SetBlockNotSent(blockpos);
2867                         }
2868                         // Placement -> above
2869                         if(action == 3){
2870                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
2871                                 client->SetBlockNotSent(blockpos);
2872                         }
2873                         return;
2874                 }
2875
2876                 /*
2877                         If something goes wrong, this player is to blame
2878                 */
2879                 RollbackScopeActor rollback_scope(m_rollback,
2880                                 std::string("player:")+player->getName());
2881
2882                 /*
2883                         0: start digging or punch object
2884                 */
2885                 if(action == 0)
2886                 {
2887                         if(pointed.type == POINTEDTHING_NODE)
2888                         {
2889                                 /*
2890                                         NOTE: This can be used in the future to check if
2891                                         somebody is cheating, by checking the timing.
2892                                 */
2893                                 MapNode n(CONTENT_IGNORE);
2894                                 try
2895                                 {
2896                                         n = m_env->getMap().getNode(p_under);
2897                                 }
2898                                 catch(InvalidPositionException &e)
2899                                 {
2900                                         infostream<<"Server: Not punching: Node not found."
2901                                                         <<" Adding block to emerge queue."
2902                                                         <<std::endl;
2903                                         m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2904                                 }
2905                                 if(n.getContent() != CONTENT_IGNORE)
2906                                         m_script->node_on_punch(p_under, n, playersao);
2907                                 // Cheat prevention
2908                                 playersao->noCheatDigStart(p_under);
2909                         }
2910                         else if(pointed.type == POINTEDTHING_OBJECT)
2911                         {
2912                                 // Skip if object has been removed
2913                                 if(pointed_object->m_removed)
2914                                         return;
2915
2916                                 actionstream<<player->getName()<<" punches object "
2917                                                 <<pointed.object_id<<": "
2918                                                 <<pointed_object->getDescription()<<std::endl;
2919
2920                                 ItemStack punchitem = playersao->getWieldedItem();
2921                                 ToolCapabilities toolcap =
2922                                                 punchitem.getToolCapabilities(m_itemdef);
2923                                 v3f dir = (pointed_object->getBasePosition() -
2924                                                 (player->getPosition() + player->getEyeOffset())
2925                                                         ).normalize();
2926                                 float time_from_last_punch =
2927                                         playersao->resetTimeFromLastPunch();
2928                                 pointed_object->punch(dir, &toolcap, playersao,
2929                                                 time_from_last_punch);
2930                         }
2931
2932                 } // action == 0
2933
2934                 /*
2935                         1: stop digging
2936                 */
2937                 else if(action == 1)
2938                 {
2939                 } // action == 1
2940
2941                 /*
2942                         2: Digging completed
2943                 */
2944                 else if(action == 2)
2945                 {
2946                         // Only digging of nodes
2947                         if(pointed.type == POINTEDTHING_NODE)
2948                         {
2949                                 MapNode n(CONTENT_IGNORE);
2950                                 try
2951                                 {
2952                                         n = m_env->getMap().getNode(p_under);
2953                                 }
2954                                 catch(InvalidPositionException &e)
2955                                 {
2956                                         infostream<<"Server: Not finishing digging: Node not found."
2957                                                         <<" Adding block to emerge queue."
2958                                                         <<std::endl;
2959                                         m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2960                                 }
2961
2962                                 /* Cheat prevention */
2963                                 bool is_valid_dig = true;
2964                                 if(!isSingleplayer() && !g_settings->getBool("disable_anticheat"))
2965                                 {
2966                                         v3s16 nocheat_p = playersao->getNoCheatDigPos();
2967                                         float nocheat_t = playersao->getNoCheatDigTime();
2968                                         playersao->noCheatDigEnd();
2969                                         // If player didn't start digging this, ignore dig
2970                                         if(nocheat_p != p_under){
2971                                                 infostream<<"Server: NoCheat: "<<player->getName()
2972                                                                 <<" started digging "
2973                                                                 <<PP(nocheat_p)<<" and completed digging "
2974                                                                 <<PP(p_under)<<"; not digging."<<std::endl;
2975                                                 is_valid_dig = false;
2976                                                 // Call callbacks
2977                                                 m_script->on_cheat(playersao, "finished_unknown_dig");
2978                                         }
2979                                         // Get player's wielded item
2980                                         ItemStack playeritem;
2981                                         InventoryList *mlist = playersao->getInventory()->getList("main");
2982                                         if(mlist != NULL)
2983                                                 playeritem = mlist->getItem(playersao->getWieldIndex());
2984                                         ToolCapabilities playeritem_toolcap =
2985                                                         playeritem.getToolCapabilities(m_itemdef);
2986                                         // Get diggability and expected digging time
2987                                         DigParams params = getDigParams(m_nodedef->get(n).groups,
2988                                                         &playeritem_toolcap);
2989                                         // If can't dig, try hand
2990                                         if(!params.diggable){
2991                                                 const ItemDefinition &hand = m_itemdef->get("");
2992                                                 const ToolCapabilities *tp = hand.tool_capabilities;
2993                                                 if(tp)
2994                                                         params = getDigParams(m_nodedef->get(n).groups, tp);
2995                                         }
2996                                         // If can't dig, ignore dig
2997                                         if(!params.diggable){
2998                                                 infostream<<"Server: NoCheat: "<<player->getName()
2999                                                                 <<" completed digging "<<PP(p_under)
3000                                                                 <<", which is not diggable with tool. not digging."
3001                                                                 <<std::endl;
3002                                                 is_valid_dig = false;
3003                                                 // Call callbacks
3004                                                 m_script->on_cheat(playersao, "dug_unbreakable");
3005                                         }
3006                                         // Check digging time
3007                                         // If already invalidated, we don't have to
3008                                         if(!is_valid_dig){
3009                                                 // Well not our problem then
3010                                         }
3011                                         // Clean and long dig
3012                                         else if(params.time > 2.0 && nocheat_t * 1.2 > params.time){
3013                                                 // All is good, but grab time from pool; don't care if
3014                                                 // it's actually available
3015                                                 playersao->getDigPool().grab(params.time);
3016                                         }
3017                                         // Short or laggy dig
3018                                         // Try getting the time from pool
3019                                         else if(playersao->getDigPool().grab(params.time)){
3020                                                 // All is good
3021                                         }
3022                                         // Dig not possible
3023                                         else{
3024                                                 infostream<<"Server: NoCheat: "<<player->getName()
3025                                                                 <<" completed digging "<<PP(p_under)
3026                                                                 <<"too fast; not digging."<<std::endl;
3027                                                 is_valid_dig = false;
3028                                                 // Call callbacks
3029                                                 m_script->on_cheat(playersao, "dug_too_fast");
3030                                         }
3031                                 }
3032
3033                                 /* Actually dig node */
3034
3035                                 if(is_valid_dig && n.getContent() != CONTENT_IGNORE)
3036                                         m_script->node_on_dig(p_under, n, playersao);
3037
3038                                 // Send unusual result (that is, node not being removed)
3039                                 if(m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR)
3040                                 {
3041                                         // Re-send block to revert change on client-side
3042                                         RemoteClient *client = getClient(peer_id);
3043                                         v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
3044                                         client->SetBlockNotSent(blockpos);
3045                                 }
3046                         }
3047                 } // action == 2
3048
3049                 /*
3050                         3: place block or right-click object
3051                 */
3052                 else if(action == 3)
3053                 {
3054                         ItemStack item = playersao->getWieldedItem();
3055
3056                         // Reset build time counter
3057                         if(pointed.type == POINTEDTHING_NODE &&
3058                                         item.getDefinition(m_itemdef).type == ITEM_NODE)
3059                                 getClient(peer_id)->m_time_from_building = 0.0;
3060
3061                         if(pointed.type == POINTEDTHING_OBJECT)
3062                         {
3063                                 // Right click object
3064
3065                                 // Skip if object has been removed
3066                                 if(pointed_object->m_removed)
3067                                         return;
3068
3069                                 actionstream<<player->getName()<<" right-clicks object "
3070                                                 <<pointed.object_id<<": "
3071                                                 <<pointed_object->getDescription()<<std::endl;
3072
3073                                 // Do stuff
3074                                 pointed_object->rightClick(playersao);
3075                         }
3076                         else if(m_script->item_OnPlace(
3077                                         item, playersao, pointed))
3078                         {
3079                                 // Placement was handled in lua
3080
3081                                 // Apply returned ItemStack
3082                                 playersao->setWieldedItem(item);
3083                         }
3084
3085                         // If item has node placement prediction, always send the
3086                         // blocks to make sure the client knows what exactly happened
3087                         if(item.getDefinition(m_itemdef).node_placement_prediction != ""){
3088                                 RemoteClient *client = getClient(peer_id);
3089                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
3090                                 client->SetBlockNotSent(blockpos);
3091                                 v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
3092                                 if(blockpos2 != blockpos){
3093                                         client->SetBlockNotSent(blockpos2);
3094                                 }
3095                         }
3096                 } // action == 3
3097
3098                 /*
3099                         4: use
3100                 */
3101                 else if(action == 4)
3102                 {
3103                         ItemStack item = playersao->getWieldedItem();
3104
3105                         actionstream<<player->getName()<<" uses "<<item.name
3106                                         <<", pointing at "<<pointed.dump()<<std::endl;
3107
3108                         if(m_script->item_OnUse(
3109                                         item, playersao, pointed))
3110                         {
3111                                 // Apply returned ItemStack
3112                                 playersao->setWieldedItem(item);
3113                         }
3114
3115                 } // action == 4
3116                 
3117
3118                 /*
3119                         Catch invalid actions
3120                 */
3121                 else
3122                 {
3123                         infostream<<"WARNING: Server: Invalid action "
3124                                         <<action<<std::endl;
3125                 }
3126         }
3127         else if(command == TOSERVER_REMOVED_SOUNDS)
3128         {
3129                 std::string datastring((char*)&data[2], datasize-2);
3130                 std::istringstream is(datastring, std::ios_base::binary);
3131
3132                 int num = readU16(is);
3133                 for(int k=0; k<num; k++){
3134                         s32 id = readS32(is);
3135                         std::map<s32, ServerPlayingSound>::iterator i =
3136                                         m_playing_sounds.find(id);
3137                         if(i == m_playing_sounds.end())
3138                                 continue;
3139                         ServerPlayingSound &psound = i->second;
3140                         psound.clients.erase(peer_id);
3141                         if(psound.clients.size() == 0)
3142                                 m_playing_sounds.erase(i++);
3143                 }
3144         }
3145         else if(command == TOSERVER_NODEMETA_FIELDS)
3146         {
3147                 std::string datastring((char*)&data[2], datasize-2);
3148                 std::istringstream is(datastring, std::ios_base::binary);
3149
3150                 v3s16 p = readV3S16(is);
3151                 std::string formname = deSerializeString(is);
3152                 int num = readU16(is);
3153                 std::map<std::string, std::string> fields;
3154                 for(int k=0; k<num; k++){
3155                         std::string fieldname = deSerializeString(is);
3156                         std::string fieldvalue = deSerializeLongString(is);
3157                         fields[fieldname] = fieldvalue;
3158                 }
3159
3160                 // If something goes wrong, this player is to blame
3161                 RollbackScopeActor rollback_scope(m_rollback,
3162                                 std::string("player:")+player->getName());
3163
3164                 // Check the target node for rollback data; leave others unnoticed
3165                 RollbackNode rn_old(&m_env->getMap(), p, this);
3166
3167                 m_script->node_on_receive_fields(p, formname, fields,playersao);
3168
3169                 // Report rollback data
3170                 RollbackNode rn_new(&m_env->getMap(), p, this);
3171                 if(rollback() && rn_new != rn_old){
3172                         RollbackAction action;
3173                         action.setSetNode(p, rn_old, rn_new);
3174                         rollback()->reportAction(action);
3175                 }
3176         }
3177         else if(command == TOSERVER_INVENTORY_FIELDS)
3178         {
3179                 std::string datastring((char*)&data[2], datasize-2);
3180                 std::istringstream is(datastring, std::ios_base::binary);
3181
3182                 std::string formname = deSerializeString(is);
3183                 int num = readU16(is);
3184                 std::map<std::string, std::string> fields;
3185                 for(int k=0; k<num; k++){
3186                         std::string fieldname = deSerializeString(is);
3187                         std::string fieldvalue = deSerializeLongString(is);
3188                         fields[fieldname] = fieldvalue;
3189                 }
3190
3191                 m_script->on_playerReceiveFields(playersao, formname, fields);
3192         }
3193         else
3194         {
3195                 infostream<<"Server::ProcessData(): Ignoring "
3196                                 "unknown command "<<command<<std::endl;
3197         }
3198
3199         } //try
3200         catch(SendFailedException &e)
3201         {
3202                 errorstream<<"Server::ProcessData(): SendFailedException: "
3203                                 <<"what="<<e.what()
3204                                 <<std::endl;
3205         }
3206 }
3207
3208 void Server::setTimeOfDay(u32 time)
3209 {
3210         m_env->setTimeOfDay(time);
3211         m_time_of_day_send_timer = 0;
3212 }
3213
3214 void Server::onMapEditEvent(MapEditEvent *event)
3215 {
3216         //infostream<<"Server::onMapEditEvent()"<<std::endl;
3217         if(m_ignore_map_edit_events)
3218                 return;
3219         if(m_ignore_map_edit_events_area.contains(event->getArea()))
3220                 return;
3221         MapEditEvent *e = event->clone();
3222         m_unsent_map_edit_queue.push_back(e);
3223 }
3224
3225 Inventory* Server::getInventory(const InventoryLocation &loc)
3226 {
3227         switch(loc.type){
3228         case InventoryLocation::UNDEFINED:
3229         {}
3230         break;
3231         case InventoryLocation::CURRENT_PLAYER:
3232         {}
3233         break;
3234         case InventoryLocation::PLAYER:
3235         {
3236                 Player *player = m_env->getPlayer(loc.name.c_str());
3237                 if(!player)
3238                         return NULL;
3239                 PlayerSAO *playersao = player->getPlayerSAO();
3240                 if(!playersao)
3241                         return NULL;
3242                 return playersao->getInventory();
3243         }
3244         break;
3245         case InventoryLocation::NODEMETA:
3246         {
3247                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3248                 if(!meta)
3249                         return NULL;
3250                 return meta->getInventory();
3251         }
3252         break;
3253         case InventoryLocation::DETACHED:
3254         {
3255                 if(m_detached_inventories.count(loc.name) == 0)
3256                         return NULL;
3257                 return m_detached_inventories[loc.name];
3258         }
3259         break;
3260         default:
3261                 assert(0);
3262         }
3263         return NULL;
3264 }
3265 void Server::setInventoryModified(const InventoryLocation &loc)
3266 {
3267         switch(loc.type){
3268         case InventoryLocation::UNDEFINED:
3269         {}
3270         break;
3271         case InventoryLocation::PLAYER:
3272         {
3273                 Player *player = m_env->getPlayer(loc.name.c_str());
3274                 if(!player)
3275                         return;
3276                 PlayerSAO *playersao = player->getPlayerSAO();
3277                 if(!playersao)
3278                         return;
3279                 playersao->m_inventory_not_sent = true;
3280                 playersao->m_wielded_item_not_sent = true;
3281         }
3282         break;
3283         case InventoryLocation::NODEMETA:
3284         {
3285                 v3s16 blockpos = getNodeBlockPos(loc.p);
3286
3287                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
3288                 if(block)
3289                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
3290
3291                 setBlockNotSent(blockpos);
3292         }
3293         break;
3294         case InventoryLocation::DETACHED:
3295         {
3296                 sendDetachedInventoryToAll(loc.name);
3297         }
3298         break;
3299         default:
3300                 assert(0);
3301         }
3302 }
3303
3304 void Server::peerAdded(con::Peer *peer)
3305 {
3306         DSTACK(__FUNCTION_NAME);
3307         verbosestream<<"Server::peerAdded(): peer->id="
3308                         <<peer->id<<std::endl;
3309
3310         PeerChange c;
3311         c.type = PEER_ADDED;
3312         c.peer_id = peer->id;
3313         c.timeout = false;
3314         m_peer_change_queue.push_back(c);
3315 }
3316
3317 void Server::deletingPeer(con::Peer *peer, bool timeout)
3318 {
3319         DSTACK(__FUNCTION_NAME);
3320         verbosestream<<"Server::deletingPeer(): peer->id="
3321                         <<peer->id<<", timeout="<<timeout<<std::endl;
3322
3323         PeerChange c;
3324         c.type = PEER_REMOVED;
3325         c.peer_id = peer->id;
3326         c.timeout = timeout;
3327         m_peer_change_queue.push_back(c);
3328 }
3329
3330 /*
3331         Static send methods
3332 */
3333
3334 void Server::SendMovement(con::Connection &con, u16 peer_id)
3335 {
3336         DSTACK(__FUNCTION_NAME);
3337         std::ostringstream os(std::ios_base::binary);
3338
3339         writeU16(os, TOCLIENT_MOVEMENT);
3340         writeF1000(os, g_settings->getFloat("movement_acceleration_default"));
3341         writeF1000(os, g_settings->getFloat("movement_acceleration_air"));
3342         writeF1000(os, g_settings->getFloat("movement_acceleration_fast"));
3343         writeF1000(os, g_settings->getFloat("movement_speed_walk"));
3344         writeF1000(os, g_settings->getFloat("movement_speed_crouch"));
3345         writeF1000(os, g_settings->getFloat("movement_speed_fast"));
3346         writeF1000(os, g_settings->getFloat("movement_speed_climb"));
3347         writeF1000(os, g_settings->getFloat("movement_speed_jump"));
3348         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity"));
3349         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity_smooth"));
3350         writeF1000(os, g_settings->getFloat("movement_liquid_sink"));
3351         writeF1000(os, g_settings->getFloat("movement_gravity"));
3352
3353         // Make data buffer
3354         std::string s = os.str();
3355         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3356         // Send as reliable
3357         con.Send(peer_id, 0, data, true);
3358 }
3359
3360 void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp)
3361 {
3362         DSTACK(__FUNCTION_NAME);
3363         std::ostringstream os(std::ios_base::binary);
3364
3365         writeU16(os, TOCLIENT_HP);
3366         writeU8(os, hp);
3367
3368         // Make data buffer
3369         std::string s = os.str();
3370         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3371         // Send as reliable
3372         con.Send(peer_id, 0, data, true);
3373 }
3374
3375 void Server::SendBreath(con::Connection &con, u16 peer_id, u16 breath)
3376 {
3377         DSTACK(__FUNCTION_NAME);
3378         std::ostringstream os(std::ios_base::binary);
3379
3380         writeU16(os, TOCLIENT_BREATH);
3381         writeU16(os, breath);
3382
3383         // Make data buffer
3384         std::string s = os.str();
3385         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3386         // Send as reliable
3387         con.Send(peer_id, 0, data, true);
3388 }
3389
3390 void Server::SendAccessDenied(con::Connection &con, u16 peer_id,
3391                 const std::wstring &reason)
3392 {
3393         DSTACK(__FUNCTION_NAME);
3394         std::ostringstream os(std::ios_base::binary);
3395
3396         writeU16(os, TOCLIENT_ACCESS_DENIED);
3397         os<<serializeWideString(reason);
3398
3399         // Make data buffer
3400         std::string s = os.str();
3401         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3402         // Send as reliable
3403         con.Send(peer_id, 0, data, true);
3404 }
3405
3406 void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
3407                 bool set_camera_point_target, v3f camera_point_target)
3408 {
3409         DSTACK(__FUNCTION_NAME);
3410         std::ostringstream os(std::ios_base::binary);
3411
3412         writeU16(os, TOCLIENT_DEATHSCREEN);
3413         writeU8(os, set_camera_point_target);
3414         writeV3F1000(os, camera_point_target);
3415
3416         // Make data buffer
3417         std::string s = os.str();
3418         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3419         // Send as reliable
3420         con.Send(peer_id, 0, data, true);
3421 }
3422
3423 void Server::SendItemDef(con::Connection &con, u16 peer_id,
3424                 IItemDefManager *itemdef, u16 protocol_version)
3425 {
3426         DSTACK(__FUNCTION_NAME);
3427         std::ostringstream os(std::ios_base::binary);
3428
3429         /*
3430                 u16 command
3431                 u32 length of the next item
3432                 zlib-compressed serialized ItemDefManager
3433         */
3434         writeU16(os, TOCLIENT_ITEMDEF);
3435         std::ostringstream tmp_os(std::ios::binary);
3436         itemdef->serialize(tmp_os, protocol_version);
3437         std::ostringstream tmp_os2(std::ios::binary);
3438         compressZlib(tmp_os.str(), tmp_os2);
3439         os<<serializeLongString(tmp_os2.str());
3440
3441         // Make data buffer
3442         std::string s = os.str();
3443         verbosestream<<"Server: Sending item definitions to id("<<peer_id
3444                         <<"): size="<<s.size()<<std::endl;
3445         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3446         // Send as reliable
3447         con.Send(peer_id, 0, data, true);
3448 }
3449
3450 void Server::SendNodeDef(con::Connection &con, u16 peer_id,
3451                 INodeDefManager *nodedef, u16 protocol_version)
3452 {
3453         DSTACK(__FUNCTION_NAME);
3454         std::ostringstream os(std::ios_base::binary);
3455
3456         /*
3457                 u16 command
3458                 u32 length of the next item
3459                 zlib-compressed serialized NodeDefManager
3460         */
3461         writeU16(os, TOCLIENT_NODEDEF);
3462         std::ostringstream tmp_os(std::ios::binary);
3463         nodedef->serialize(tmp_os, protocol_version);
3464         std::ostringstream tmp_os2(std::ios::binary);
3465         compressZlib(tmp_os.str(), tmp_os2);
3466         os<<serializeLongString(tmp_os2.str());
3467
3468         // Make data buffer
3469         std::string s = os.str();
3470         verbosestream<<"Server: Sending node definitions to id("<<peer_id
3471                         <<"): size="<<s.size()<<std::endl;
3472         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3473         // Send as reliable
3474         con.Send(peer_id, 0, data, true);
3475 }
3476
3477 /*
3478         Non-static send methods
3479 */
3480
3481 void Server::SendInventory(u16 peer_id)
3482 {
3483         DSTACK(__FUNCTION_NAME);
3484
3485         PlayerSAO *playersao = getPlayerSAO(peer_id);
3486         assert(playersao);
3487
3488         playersao->m_inventory_not_sent = false;
3489
3490         /*
3491                 Serialize it
3492         */
3493
3494         std::ostringstream os;
3495         playersao->getInventory()->serialize(os);
3496
3497         std::string s = os.str();
3498
3499         SharedBuffer<u8> data(s.size()+2);
3500         writeU16(&data[0], TOCLIENT_INVENTORY);
3501         memcpy(&data[2], s.c_str(), s.size());
3502
3503         // Send as reliable
3504         m_con.Send(peer_id, 0, data, true);
3505 }
3506
3507 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
3508 {
3509         DSTACK(__FUNCTION_NAME);
3510
3511         std::ostringstream os(std::ios_base::binary);
3512         u8 buf[12];
3513
3514         // Write command
3515         writeU16(buf, TOCLIENT_CHAT_MESSAGE);
3516         os.write((char*)buf, 2);
3517
3518         // Write length
3519         writeU16(buf, message.size());
3520         os.write((char*)buf, 2);
3521
3522         // Write string
3523         for(u32 i=0; i<message.size(); i++)
3524         {
3525                 u16 w = message[i];
3526                 writeU16(buf, w);
3527                 os.write((char*)buf, 2);
3528         }
3529
3530         // Make data buffer
3531         std::string s = os.str();
3532         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3533         // Send as reliable
3534         m_con.Send(peer_id, 0, data, true);
3535 }
3536
3537 void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec,
3538                                         const std::string formname)
3539 {
3540         DSTACK(__FUNCTION_NAME);
3541
3542         std::ostringstream os(std::ios_base::binary);
3543         u8 buf[12];
3544
3545         // Write command
3546         writeU16(buf, TOCLIENT_SHOW_FORMSPEC);
3547         os.write((char*)buf, 2);
3548         os<<serializeLongString(formspec);
3549         os<<serializeString(formname);
3550
3551         // Make data buffer
3552         std::string s = os.str();
3553         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3554         // Send as reliable
3555         m_con.Send(peer_id, 0, data, true);
3556 }
3557
3558 // Spawns a particle on peer with peer_id
3559 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
3560                                 float expirationtime, float size, bool collisiondetection,
3561                                 std::string texture)
3562 {
3563         DSTACK(__FUNCTION_NAME);
3564
3565         std::ostringstream os(std::ios_base::binary);
3566         writeU16(os, TOCLIENT_SPAWN_PARTICLE);
3567         writeV3F1000(os, pos);
3568         writeV3F1000(os, velocity);
3569         writeV3F1000(os, acceleration);
3570         writeF1000(os, expirationtime);
3571         writeF1000(os, size);
3572         writeU8(os,  collisiondetection);
3573         os<<serializeLongString(texture);
3574
3575         // Make data buffer
3576         std::string s = os.str();
3577         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3578         // Send as reliable
3579         m_con.Send(peer_id, 0, data, true);
3580 }
3581
3582 // Spawns a particle on all peers
3583 void Server::SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
3584                                 float expirationtime, float size, bool collisiondetection,
3585                                 std::string texture)
3586 {
3587         for(std::map<u16, RemoteClient*>::iterator
3588                 i = m_clients.begin();
3589                 i != m_clients.end(); i++)
3590         {
3591                 // Get client and check that it is valid
3592                 RemoteClient *client = i->second;
3593                 assert(client->peer_id == i->first);
3594                 if(client->serialization_version == SER_FMT_VER_INVALID)
3595                         continue;
3596
3597                 SendSpawnParticle(client->peer_id, pos, velocity, acceleration,
3598                         expirationtime, size, collisiondetection, texture);
3599         }
3600 }
3601
3602 // Adds a ParticleSpawner on peer with peer_id
3603 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
3604         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3605         float minsize, float maxsize, bool collisiondetection, std::string texture, u32 id)
3606 {
3607         DSTACK(__FUNCTION_NAME);
3608
3609         std::ostringstream os(std::ios_base::binary);
3610         writeU16(os, TOCLIENT_ADD_PARTICLESPAWNER);
3611
3612         writeU16(os, amount);
3613         writeF1000(os, spawntime);
3614         writeV3F1000(os, minpos);
3615         writeV3F1000(os, maxpos);
3616         writeV3F1000(os, minvel);
3617         writeV3F1000(os, maxvel);
3618         writeV3F1000(os, minacc);
3619         writeV3F1000(os, maxacc);
3620         writeF1000(os, minexptime);
3621         writeF1000(os, maxexptime);
3622         writeF1000(os, minsize);
3623         writeF1000(os, maxsize);
3624         writeU8(os,  collisiondetection);
3625         os<<serializeLongString(texture);
3626         writeU32(os, id);
3627
3628         // Make data buffer
3629         std::string s = os.str();
3630         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3631         // Send as reliable
3632         m_con.Send(peer_id, 0, data, true);
3633 }
3634
3635 // Adds a ParticleSpawner on all peers
3636 void Server::SendAddParticleSpawnerAll(u16 amount, float spawntime, v3f minpos, v3f maxpos,
3637         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3638         float minsize, float maxsize, bool collisiondetection, std::string texture, u32 id)
3639 {
3640         for(std::map<u16, RemoteClient*>::iterator
3641                 i = m_clients.begin();
3642                 i != m_clients.end(); i++)
3643         {
3644                 // Get client and check that it is valid
3645                 RemoteClient *client = i->second;
3646                 assert(client->peer_id == i->first);
3647                 if(client->serialization_version == SER_FMT_VER_INVALID)
3648                         continue;
3649
3650                 SendAddParticleSpawner(client->peer_id, amount, spawntime,
3651                         minpos, maxpos, minvel, maxvel, minacc, maxacc,
3652                         minexptime, maxexptime, minsize, maxsize, collisiondetection, texture, id);
3653         }
3654 }
3655
3656 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
3657 {
3658         DSTACK(__FUNCTION_NAME);
3659
3660         std::ostringstream os(std::ios_base::binary);
3661         writeU16(os, TOCLIENT_DELETE_PARTICLESPAWNER);
3662
3663         writeU16(os, id);
3664
3665         // Make data buffer
3666         std::string s = os.str();
3667         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3668         // Send as reliable
3669         m_con.Send(peer_id, 0, data, true);
3670 }
3671
3672 void Server::SendDeleteParticleSpawnerAll(u32 id)
3673 {
3674         for(std::map<u16, RemoteClient*>::iterator
3675                 i = m_clients.begin();
3676                 i != m_clients.end(); i++)
3677         {
3678                 // Get client and check that it is valid
3679                 RemoteClient *client = i->second;
3680                 assert(client->peer_id == i->first);
3681                 if(client->serialization_version == SER_FMT_VER_INVALID)
3682                         continue;
3683
3684                 SendDeleteParticleSpawner(client->peer_id, id);
3685         }
3686 }
3687
3688 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
3689 {
3690         std::ostringstream os(std::ios_base::binary);
3691
3692         // Write command
3693         writeU16(os, TOCLIENT_HUDADD);
3694         writeU32(os, id);
3695         writeU8(os, (u8)form->type);
3696         writeV2F1000(os, form->pos);
3697         os << serializeString(form->name);
3698         writeV2F1000(os, form->scale);
3699         os << serializeString(form->text);
3700         writeU32(os, form->number);
3701         writeU32(os, form->item);
3702         writeU32(os, form->dir);
3703         writeV2F1000(os, form->align);
3704         writeV2F1000(os, form->offset);
3705
3706         // Make data buffer
3707         std::string s = os.str();
3708         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3709         // Send as reliable
3710         m_con.Send(peer_id, 0, data, true);
3711 }
3712
3713 void Server::SendHUDRemove(u16 peer_id, u32 id)
3714 {
3715         std::ostringstream os(std::ios_base::binary);
3716
3717         // Write command
3718         writeU16(os, TOCLIENT_HUDRM);
3719         writeU32(os, id);
3720
3721         // Make data buffer
3722         std::string s = os.str();
3723         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3724         // Send as reliable
3725         m_con.Send(peer_id, 0, data, true);
3726 }
3727
3728 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
3729 {
3730         std::ostringstream os(std::ios_base::binary);
3731
3732         // Write command
3733         writeU16(os, TOCLIENT_HUDCHANGE);
3734         writeU32(os, id);
3735         writeU8(os, (u8)stat);
3736         switch (stat) {
3737                 case HUD_STAT_POS:
3738                 case HUD_STAT_SCALE:
3739                 case HUD_STAT_ALIGN:
3740                 case HUD_STAT_OFFSET:
3741                         writeV2F1000(os, *(v2f *)value);
3742                         break;
3743                 case HUD_STAT_NAME:
3744                 case HUD_STAT_TEXT:
3745                         os << serializeString(*(std::string *)value);
3746                         break;
3747                 case HUD_STAT_NUMBER:
3748                 case HUD_STAT_ITEM:
3749                 case HUD_STAT_DIR:
3750                 default:
3751                         writeU32(os, *(u32 *)value);
3752                         break;
3753         }
3754
3755         // Make data buffer
3756         std::string s = os.str();
3757         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3758         // Send as reliable
3759         m_con.Send(peer_id, 0, data, true);
3760 }
3761
3762 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
3763 {
3764         std::ostringstream os(std::ios_base::binary);
3765
3766         // Write command
3767         writeU16(os, TOCLIENT_HUD_SET_FLAGS);
3768         writeU32(os, flags);
3769         writeU32(os, mask);
3770
3771         // Make data buffer
3772         std::string s = os.str();
3773         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3774         // Send as reliable
3775         m_con.Send(peer_id, 0, data, true);
3776 }
3777
3778 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
3779 {
3780         std::ostringstream os(std::ios_base::binary);
3781
3782         // Write command
3783         writeU16(os, TOCLIENT_HUD_SET_PARAM);
3784         writeU16(os, param);
3785         os<<serializeString(value);
3786
3787         // Make data buffer
3788         std::string s = os.str();
3789         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3790         // Send as reliable
3791         m_con.Send(peer_id, 0, data, true);
3792 }
3793
3794 void Server::BroadcastChatMessage(const std::wstring &message)
3795 {
3796         for(std::map<u16, RemoteClient*>::iterator
3797                 i = m_clients.begin();
3798                 i != m_clients.end(); ++i)
3799         {
3800                 // Get client and check that it is valid
3801                 RemoteClient *client = i->second;
3802                 assert(client->peer_id == i->first);
3803                 if(client->serialization_version == SER_FMT_VER_INVALID)
3804                         continue;
3805
3806                 SendChatMessage(client->peer_id, message);
3807         }
3808 }
3809
3810 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
3811 {
3812         DSTACK(__FUNCTION_NAME);
3813
3814         // Make packet
3815         SharedBuffer<u8> data(2+2+4);
3816         writeU16(&data[0], TOCLIENT_TIME_OF_DAY);
3817         writeU16(&data[2], time);
3818         writeF1000(&data[4], time_speed);
3819
3820         // Send as reliable
3821         m_con.Send(peer_id, 0, data, true);
3822 }
3823
3824 void Server::SendPlayerHP(u16 peer_id)
3825 {
3826         DSTACK(__FUNCTION_NAME);
3827         PlayerSAO *playersao = getPlayerSAO(peer_id);
3828         assert(playersao);
3829         playersao->m_hp_not_sent = false;
3830         SendHP(m_con, peer_id, playersao->getHP());
3831
3832         // Send to other clients
3833         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
3834         ActiveObjectMessage aom(playersao->getId(), true, str);
3835         playersao->m_messages_out.push_back(aom);
3836 }
3837
3838 void Server::SendPlayerBreath(u16 peer_id)
3839 {
3840         DSTACK(__FUNCTION_NAME);
3841         PlayerSAO *playersao = getPlayerSAO(peer_id);
3842         assert(playersao);
3843         playersao->m_breath_not_sent = false;
3844         SendBreath(m_con, peer_id, playersao->getBreath());
3845 }
3846
3847 void Server::SendMovePlayer(u16 peer_id)
3848 {
3849         DSTACK(__FUNCTION_NAME);
3850         Player *player = m_env->getPlayer(peer_id);
3851         assert(player);
3852
3853         std::ostringstream os(std::ios_base::binary);
3854         writeU16(os, TOCLIENT_MOVE_PLAYER);
3855         writeV3F1000(os, player->getPosition());
3856         writeF1000(os, player->getPitch());
3857         writeF1000(os, player->getYaw());
3858
3859         {
3860                 v3f pos = player->getPosition();
3861                 f32 pitch = player->getPitch();
3862                 f32 yaw = player->getYaw();
3863                 verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
3864                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3865                                 <<" pitch="<<pitch
3866                                 <<" yaw="<<yaw
3867                                 <<std::endl;
3868         }
3869
3870         // Make data buffer
3871         std::string s = os.str();
3872         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3873         // Send as reliable
3874         m_con.Send(peer_id, 0, data, true);
3875 }
3876
3877 void Server::SendPlayerPrivileges(u16 peer_id)
3878 {
3879         Player *player = m_env->getPlayer(peer_id);
3880         assert(player);
3881         if(player->peer_id == PEER_ID_INEXISTENT)
3882                 return;
3883
3884         std::set<std::string> privs;
3885         m_script->getAuth(player->getName(), NULL, &privs);
3886
3887         std::ostringstream os(std::ios_base::binary);
3888         writeU16(os, TOCLIENT_PRIVILEGES);
3889         writeU16(os, privs.size());
3890         for(std::set<std::string>::const_iterator i = privs.begin();
3891                         i != privs.end(); i++){
3892                 os<<serializeString(*i);
3893         }
3894
3895         // Make data buffer
3896         std::string s = os.str();
3897         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3898         // Send as reliable
3899         m_con.Send(peer_id, 0, data, true);
3900 }
3901
3902 void Server::SendPlayerInventoryFormspec(u16 peer_id)
3903 {
3904         Player *player = m_env->getPlayer(peer_id);
3905         assert(player);
3906         if(player->peer_id == PEER_ID_INEXISTENT)
3907                 return;
3908
3909         std::ostringstream os(std::ios_base::binary);
3910         writeU16(os, TOCLIENT_INVENTORY_FORMSPEC);
3911         os<<serializeLongString(player->inventory_formspec);
3912
3913         // Make data buffer
3914         std::string s = os.str();
3915         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3916         // Send as reliable
3917         m_con.Send(peer_id, 0, data, true);
3918 }
3919
3920 s32 Server::playSound(const SimpleSoundSpec &spec,
3921                 const ServerSoundParams &params)
3922 {
3923         // Find out initial position of sound
3924         bool pos_exists = false;
3925         v3f pos = params.getPos(m_env, &pos_exists);
3926         // If position is not found while it should be, cancel sound
3927         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
3928                 return -1;
3929         // Filter destination clients
3930         std::set<RemoteClient*> dst_clients;
3931         if(params.to_player != "")
3932         {
3933                 Player *player = m_env->getPlayer(params.to_player.c_str());
3934                 if(!player){
3935                         infostream<<"Server::playSound: Player \""<<params.to_player
3936                                         <<"\" not found"<<std::endl;
3937                         return -1;
3938                 }
3939                 if(player->peer_id == PEER_ID_INEXISTENT){
3940                         infostream<<"Server::playSound: Player \""<<params.to_player
3941                                         <<"\" not connected"<<std::endl;
3942                         return -1;
3943                 }
3944                 RemoteClient *client = getClient(player->peer_id);
3945                 dst_clients.insert(client);
3946         }
3947         else
3948         {
3949                 for(std::map<u16, RemoteClient*>::iterator
3950                                 i = m_clients.begin(); i != m_clients.end(); ++i)
3951                 {
3952                         RemoteClient *client = i->second;
3953                         Player *player = m_env->getPlayer(client->peer_id);
3954                         if(!player)
3955                                 continue;
3956                         if(pos_exists){
3957                                 if(player->getPosition().getDistanceFrom(pos) >
3958                                                 params.max_hear_distance)
3959                                         continue;
3960                         }
3961                         dst_clients.insert(client);
3962                 }
3963         }
3964         if(dst_clients.size() == 0)
3965                 return -1;
3966         // Create the sound
3967         s32 id = m_next_sound_id++;
3968         // The sound will exist as a reference in m_playing_sounds
3969         m_playing_sounds[id] = ServerPlayingSound();
3970         ServerPlayingSound &psound = m_playing_sounds[id];
3971         psound.params = params;
3972         for(std::set<RemoteClient*>::iterator i = dst_clients.begin();
3973                         i != dst_clients.end(); i++)
3974                 psound.clients.insert((*i)->peer_id);
3975         // Create packet
3976         std::ostringstream os(std::ios_base::binary);
3977         writeU16(os, TOCLIENT_PLAY_SOUND);
3978         writeS32(os, id);
3979         os<<serializeString(spec.name);
3980         writeF1000(os, spec.gain * params.gain);
3981         writeU8(os, params.type);
3982         writeV3F1000(os, pos);
3983         writeU16(os, params.object);
3984         writeU8(os, params.loop);
3985         // Make data buffer
3986         std::string s = os.str();
3987         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3988         // Send
3989         for(std::set<RemoteClient*>::iterator i = dst_clients.begin();
3990                         i != dst_clients.end(); i++){
3991                 // Send as reliable
3992                 m_con.Send((*i)->peer_id, 0, data, true);
3993         }
3994         return id;
3995 }
3996 void Server::stopSound(s32 handle)
3997 {
3998         // Get sound reference
3999         std::map<s32, ServerPlayingSound>::iterator i =
4000                         m_playing_sounds.find(handle);
4001         if(i == m_playing_sounds.end())
4002                 return;
4003         ServerPlayingSound &psound = i->second;
4004         // Create packet
4005         std::ostringstream os(std::ios_base::binary);
4006         writeU16(os, TOCLIENT_STOP_SOUND);
4007         writeS32(os, handle);
4008         // Make data buffer
4009         std::string s = os.str();
4010         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4011         // Send
4012         for(std::set<u16>::iterator i = psound.clients.begin();
4013                         i != psound.clients.end(); i++){
4014                 // Send as reliable
4015                 m_con.Send(*i, 0, data, true);
4016         }
4017         // Remove sound reference
4018         m_playing_sounds.erase(i);
4019 }
4020
4021 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
4022         std::list<u16> *far_players, float far_d_nodes)
4023 {
4024         float maxd = far_d_nodes*BS;
4025         v3f p_f = intToFloat(p, BS);
4026
4027         // Create packet
4028         u32 replysize = 8;
4029         SharedBuffer<u8> reply(replysize);
4030         writeU16(&reply[0], TOCLIENT_REMOVENODE);
4031         writeS16(&reply[2], p.X);
4032         writeS16(&reply[4], p.Y);
4033         writeS16(&reply[6], p.Z);
4034
4035         for(std::map<u16, RemoteClient*>::iterator
4036                 i = m_clients.begin();
4037                 i != m_clients.end(); ++i)
4038         {
4039                 // Get client and check that it is valid
4040                 RemoteClient *client = i->second;
4041                 assert(client->peer_id == i->first);
4042                 if(client->serialization_version == SER_FMT_VER_INVALID)
4043                         continue;
4044
4045                 // Don't send if it's the same one
4046                 if(client->peer_id == ignore_id)
4047                         continue;
4048
4049                 if(far_players)
4050                 {
4051                         // Get player
4052                         Player *player = m_env->getPlayer(client->peer_id);
4053                         if(player)
4054                         {
4055                                 // If player is far away, only set modified blocks not sent
4056                                 v3f player_pos = player->getPosition();
4057                                 if(player_pos.getDistanceFrom(p_f) > maxd)
4058                                 {
4059                                         far_players->push_back(client->peer_id);
4060                                         continue;
4061                                 }
4062                         }
4063                 }
4064
4065                 // Send as reliable
4066                 m_con.Send(client->peer_id, 0, reply, true);
4067         }
4068 }
4069
4070 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
4071                 std::list<u16> *far_players, float far_d_nodes,
4072                 bool remove_metadata)
4073 {
4074         float maxd = far_d_nodes*BS;
4075         v3f p_f = intToFloat(p, BS);
4076
4077         for(std::map<u16, RemoteClient*>::iterator
4078                 i = m_clients.begin();
4079                 i != m_clients.end(); ++i)
4080         {
4081                 // Get client and check that it is valid
4082                 RemoteClient *client = i->second;
4083                 assert(client->peer_id == i->first);
4084                 if(client->serialization_version == SER_FMT_VER_INVALID)
4085                         continue;
4086
4087                 // Don't send if it's the same one
4088                 if(client->peer_id == ignore_id)
4089                         continue;
4090
4091                 if(far_players)
4092                 {
4093                         // Get player
4094                         Player *player = m_env->getPlayer(client->peer_id);
4095                         if(player)
4096                         {
4097                                 // If player is far away, only set modified blocks not sent
4098                                 v3f player_pos = player->getPosition();
4099                                 if(player_pos.getDistanceFrom(p_f) > maxd)
4100                                 {
4101                                         far_players->push_back(client->peer_id);
4102                                         continue;
4103                                 }
4104                         }
4105                 }
4106
4107                 // Create packet
4108                 u32 replysize = 9 + MapNode::serializedLength(client->serialization_version);
4109                 SharedBuffer<u8> reply(replysize);
4110                 writeU16(&reply[0], TOCLIENT_ADDNODE);
4111                 writeS16(&reply[2], p.X);
4112                 writeS16(&reply[4], p.Y);
4113                 writeS16(&reply[6], p.Z);
4114                 n.serialize(&reply[8], client->serialization_version);
4115                 u32 index = 8 + MapNode::serializedLength(client->serialization_version);
4116                 writeU8(&reply[index], remove_metadata ? 0 : 1);
4117                 
4118                 if (!remove_metadata) {
4119                         if (client->net_proto_version <= 21) {
4120                                 // Old clients always clear metadata; fix it
4121                                 // by sending the full block again.
4122                                 client->SetBlockNotSent(p);
4123                         }
4124                 }
4125
4126                 // Send as reliable
4127                 m_con.Send(client->peer_id, 0, reply, true);
4128         }
4129 }
4130
4131 void Server::setBlockNotSent(v3s16 p)
4132 {
4133         for(std::map<u16, RemoteClient*>::iterator
4134                 i = m_clients.begin();
4135                 i != m_clients.end(); ++i)
4136         {
4137                 RemoteClient *client = i->second;
4138                 client->SetBlockNotSent(p);
4139         }
4140 }
4141
4142 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
4143 {
4144         DSTACK(__FUNCTION_NAME);
4145
4146         v3s16 p = block->getPos();
4147
4148 #if 0
4149         // Analyze it a bit
4150         bool completely_air = true;
4151         for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
4152         for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
4153         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
4154         {
4155                 if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
4156                 {
4157                         completely_air = false;
4158                         x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
4159                 }
4160         }
4161
4162         // Print result
4163         infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
4164         if(completely_air)
4165                 infostream<<"[completely air] ";
4166         infostream<<std::endl;
4167 #endif
4168
4169         /*
4170                 Create a packet with the block in the right format
4171         */
4172
4173         std::ostringstream os(std::ios_base::binary);
4174         block->serialize(os, ver, false);
4175         block->serializeNetworkSpecific(os, net_proto_version);
4176         std::string s = os.str();
4177         SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
4178
4179         u32 replysize = 8 + blockdata.getSize();
4180         SharedBuffer<u8> reply(replysize);
4181         writeU16(&reply[0], TOCLIENT_BLOCKDATA);
4182         writeS16(&reply[2], p.X);
4183         writeS16(&reply[4], p.Y);
4184         writeS16(&reply[6], p.Z);
4185         memcpy(&reply[8], *blockdata, blockdata.getSize());
4186
4187         /*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
4188                         <<":  \tpacket size: "<<replysize<<std::endl;*/
4189
4190         /*
4191                 Send packet
4192         */
4193         m_con.Send(peer_id, 1, reply, true);
4194 }
4195
4196 void Server::SendBlocks(float dtime)
4197 {
4198         DSTACK(__FUNCTION_NAME);
4199
4200         JMutexAutoLock envlock(m_env_mutex);
4201         JMutexAutoLock conlock(m_con_mutex);
4202
4203         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
4204
4205         std::vector<PrioritySortedBlockTransfer> queue;
4206
4207         s32 total_sending = 0;
4208
4209         {
4210                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
4211
4212                 for(std::map<u16, RemoteClient*>::iterator
4213                         i = m_clients.begin();
4214                         i != m_clients.end(); ++i)
4215                 {
4216                         RemoteClient *client = i->second;
4217                         assert(client->peer_id == i->first);
4218
4219                         // If definitions and textures have not been sent, don't
4220                         // send MapBlocks either
4221                         if(!client->definitions_sent)
4222                                 continue;
4223
4224                         total_sending += client->SendingCount();
4225
4226                         if(client->serialization_version == SER_FMT_VER_INVALID)
4227                                 continue;
4228
4229                         client->GetNextBlocks(this, dtime, queue);
4230                 }
4231         }
4232
4233         // Sort.
4234         // Lowest priority number comes first.
4235         // Lowest is most important.
4236         std::sort(queue.begin(), queue.end());
4237
4238         for(u32 i=0; i<queue.size(); i++)
4239         {
4240                 //TODO: Calculate limit dynamically
4241                 if(total_sending >= g_settings->getS32
4242                                 ("max_simultaneous_block_sends_server_total"))
4243                         break;
4244
4245                 PrioritySortedBlockTransfer q = queue[i];
4246
4247                 MapBlock *block = NULL;
4248                 try
4249                 {
4250                         block = m_env->getMap().getBlockNoCreate(q.pos);
4251                 }
4252                 catch(InvalidPositionException &e)
4253                 {
4254                         continue;
4255                 }
4256
4257                 RemoteClient *client = getClientNoEx(q.peer_id);
4258                 if(!client)
4259                         continue;
4260                 if(client->denied)
4261                         continue;
4262
4263                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
4264
4265                 client->SentBlock(q.pos);
4266
4267                 total_sending++;
4268         }
4269 }
4270
4271 void Server::fillMediaCache()
4272 {
4273         DSTACK(__FUNCTION_NAME);
4274
4275         infostream<<"Server: Calculating media file checksums"<<std::endl;
4276
4277         // Collect all media file paths
4278         std::list<std::string> paths;
4279         for(std::vector<ModSpec>::iterator i = m_mods.begin();
4280                         i != m_mods.end(); i++){
4281                 const ModSpec &mod = *i;
4282                 paths.push_back(mod.path + DIR_DELIM + "textures");
4283                 paths.push_back(mod.path + DIR_DELIM + "sounds");
4284                 paths.push_back(mod.path + DIR_DELIM + "media");
4285                 paths.push_back(mod.path + DIR_DELIM + "models");
4286         }
4287         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
4288
4289         // Collect media file information from paths into cache
4290         for(std::list<std::string>::iterator i = paths.begin();
4291                         i != paths.end(); i++)
4292         {
4293                 std::string mediapath = *i;
4294                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
4295                 for(u32 j=0; j<dirlist.size(); j++){
4296                         if(dirlist[j].dir) // Ignode dirs
4297                                 continue;
4298                         std::string filename = dirlist[j].name;
4299                         // If name contains illegal characters, ignore the file
4300                         if(!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)){
4301                                 infostream<<"Server: ignoring illegal file name: \""
4302                                                 <<filename<<"\""<<std::endl;
4303                                 continue;
4304                         }
4305                         // If name is not in a supported format, ignore it
4306                         const char *supported_ext[] = {
4307                                 ".png", ".jpg", ".bmp", ".tga",
4308                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
4309                                 ".ogg",
4310                                 ".x", ".b3d", ".md2", ".obj",
4311                                 NULL
4312                         };
4313                         if(removeStringEnd(filename, supported_ext) == ""){
4314                                 infostream<<"Server: ignoring unsupported file extension: \""
4315                                                 <<filename<<"\""<<std::endl;
4316                                 continue;
4317                         }
4318                         // Ok, attempt to load the file and add to cache
4319                         std::string filepath = mediapath + DIR_DELIM + filename;
4320                         // Read data
4321                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
4322                         if(fis.good() == false){
4323                                 errorstream<<"Server::fillMediaCache(): Could not open \""
4324                                                 <<filename<<"\" for reading"<<std::endl;
4325                                 continue;
4326                         }
4327                         std::ostringstream tmp_os(std::ios_base::binary);
4328                         bool bad = false;
4329                         for(;;){
4330                                 char buf[1024];
4331                                 fis.read(buf, 1024);
4332                                 std::streamsize len = fis.gcount();
4333                                 tmp_os.write(buf, len);
4334                                 if(fis.eof())
4335                                         break;
4336                                 if(!fis.good()){
4337                                         bad = true;
4338                                         break;
4339                                 }
4340                         }
4341                         if(bad){
4342                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
4343                                                 <<filename<<"\""<<std::endl;
4344                                 continue;
4345                         }
4346                         if(tmp_os.str().length() == 0){
4347                                 errorstream<<"Server::fillMediaCache(): Empty file \""
4348                                                 <<filepath<<"\""<<std::endl;
4349                                 continue;
4350                         }
4351
4352                         SHA1 sha1;
4353                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
4354
4355                         unsigned char *digest = sha1.getDigest();
4356                         std::string sha1_base64 = base64_encode(digest, 20);
4357                         std::string sha1_hex = hex_encode((char*)digest, 20);
4358                         free(digest);
4359
4360                         // Put in list
4361                         this->m_media[filename] = MediaInfo(filepath, sha1_base64);
4362                         verbosestream<<"Server: "<<sha1_hex<<" is "<<filename<<std::endl;
4363                 }
4364         }
4365 }
4366
4367 struct SendableMediaAnnouncement
4368 {
4369         std::string name;
4370         std::string sha1_digest;
4371
4372         SendableMediaAnnouncement(const std::string name_="",
4373                         const std::string sha1_digest_=""):
4374                 name(name_),
4375                 sha1_digest(sha1_digest_)
4376         {}
4377 };
4378
4379 void Server::sendMediaAnnouncement(u16 peer_id)
4380 {
4381         DSTACK(__FUNCTION_NAME);
4382
4383         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
4384                         <<std::endl;
4385
4386         std::list<SendableMediaAnnouncement> file_announcements;
4387
4388         for(std::map<std::string, MediaInfo>::iterator i = m_media.begin();
4389                         i != m_media.end(); i++){
4390                 // Put in list
4391                 file_announcements.push_back(
4392                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
4393         }
4394
4395         // Make packet
4396         std::ostringstream os(std::ios_base::binary);
4397
4398         /*
4399                 u16 command
4400                 u32 number of files
4401                 for each texture {
4402                         u16 length of name
4403                         string name
4404                         u16 length of sha1_digest
4405                         string sha1_digest
4406                 }
4407         */
4408
4409         writeU16(os, TOCLIENT_ANNOUNCE_MEDIA);
4410         writeU16(os, file_announcements.size());
4411
4412         for(std::list<SendableMediaAnnouncement>::iterator
4413                         j = file_announcements.begin();
4414                         j != file_announcements.end(); ++j){
4415                 os<<serializeString(j->name);
4416                 os<<serializeString(j->sha1_digest);
4417         }
4418         os<<serializeString(g_settings->get("remote_media"));
4419
4420         // Make data buffer
4421         std::string s = os.str();
4422         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4423
4424         // Send as reliable
4425         m_con.Send(peer_id, 0, data, true);
4426 }
4427
4428 struct SendableMedia
4429 {
4430         std::string name;
4431         std::string path;
4432         std::string data;
4433
4434         SendableMedia(const std::string &name_="", const std::string path_="",
4435                         const std::string &data_=""):
4436                 name(name_),
4437                 path(path_),
4438                 data(data_)
4439         {}
4440 };
4441
4442 void Server::sendRequestedMedia(u16 peer_id,
4443                 const std::list<MediaRequest> &tosend)
4444 {
4445         DSTACK(__FUNCTION_NAME);
4446
4447         verbosestream<<"Server::sendRequestedMedia(): "
4448                         <<"Sending files to client"<<std::endl;
4449
4450         /* Read files */
4451
4452         // Put 5kB in one bunch (this is not accurate)
4453         u32 bytes_per_bunch = 5000;
4454
4455         std::vector< std::list<SendableMedia> > file_bunches;
4456         file_bunches.push_back(std::list<SendableMedia>());
4457
4458         u32 file_size_bunch_total = 0;
4459
4460         for(std::list<MediaRequest>::const_iterator i = tosend.begin();
4461                         i != tosend.end(); ++i)
4462         {
4463                 if(m_media.find(i->name) == m_media.end()){
4464                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
4465                                         <<"unknown file \""<<(i->name)<<"\""<<std::endl;
4466                         continue;
4467                 }
4468
4469                 //TODO get path + name
4470                 std::string tpath = m_media[(*i).name].path;
4471
4472                 // Read data
4473                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
4474                 if(fis.good() == false){
4475                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
4476                                         <<tpath<<"\" for reading"<<std::endl;
4477                         continue;
4478                 }
4479                 std::ostringstream tmp_os(std::ios_base::binary);
4480                 bool bad = false;
4481                 for(;;){
4482                         char buf[1024];
4483                         fis.read(buf, 1024);
4484                         std::streamsize len = fis.gcount();
4485                         tmp_os.write(buf, len);
4486                         file_size_bunch_total += len;
4487                         if(fis.eof())
4488                                 break;
4489                         if(!fis.good()){
4490                                 bad = true;
4491                                 break;
4492                         }
4493                 }
4494                 if(bad){
4495                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
4496                                         <<(*i).name<<"\""<<std::endl;
4497                         continue;
4498                 }
4499                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
4500                                 <<tname<<"\""<<std::endl;*/
4501                 // Put in list
4502                 file_bunches[file_bunches.size()-1].push_back(
4503                                 SendableMedia((*i).name, tpath, tmp_os.str()));
4504
4505                 // Start next bunch if got enough data
4506                 if(file_size_bunch_total >= bytes_per_bunch){
4507                         file_bunches.push_back(std::list<SendableMedia>());
4508                         file_size_bunch_total = 0;
4509                 }
4510
4511         }
4512
4513         /* Create and send packets */
4514
4515         u32 num_bunches = file_bunches.size();
4516         for(u32 i=0; i<num_bunches; i++)
4517         {
4518                 std::ostringstream os(std::ios_base::binary);
4519
4520                 /*
4521                         u16 command
4522                         u16 total number of texture bunches
4523                         u16 index of this bunch
4524                         u32 number of files in this bunch
4525                         for each file {
4526                                 u16 length of name
4527                                 string name
4528                                 u32 length of data
4529                                 data
4530                         }
4531                 */
4532
4533                 writeU16(os, TOCLIENT_MEDIA);
4534                 writeU16(os, num_bunches);
4535                 writeU16(os, i);
4536                 writeU32(os, file_bunches[i].size());
4537
4538                 for(std::list<SendableMedia>::iterator
4539                                 j = file_bunches[i].begin();
4540                                 j != file_bunches[i].end(); ++j){
4541                         os<<serializeString(j->name);
4542                         os<<serializeLongString(j->data);
4543                 }
4544
4545                 // Make data buffer
4546                 std::string s = os.str();
4547                 verbosestream<<"Server::sendRequestedMedia(): bunch "
4548                                 <<i<<"/"<<num_bunches
4549                                 <<" files="<<file_bunches[i].size()
4550                                 <<" size=" <<s.size()<<std::endl;
4551                 SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4552                 // Send as reliable
4553                 m_con.Send(peer_id, 0, data, true);
4554         }
4555 }
4556
4557 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
4558 {
4559         if(m_detached_inventories.count(name) == 0){
4560                 errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
4561                 return;
4562         }
4563         Inventory *inv = m_detached_inventories[name];
4564
4565         std::ostringstream os(std::ios_base::binary);
4566         writeU16(os, TOCLIENT_DETACHED_INVENTORY);
4567         os<<serializeString(name);
4568         inv->serialize(os);
4569
4570         // Make data buffer
4571         std::string s = os.str();
4572         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4573         // Send as reliable
4574         m_con.Send(peer_id, 0, data, true);
4575 }
4576
4577 void Server::sendDetachedInventoryToAll(const std::string &name)
4578 {
4579         DSTACK(__FUNCTION_NAME);
4580
4581         for(std::map<u16, RemoteClient*>::iterator
4582                         i = m_clients.begin();
4583                         i != m_clients.end(); ++i){
4584                 RemoteClient *client = i->second;
4585                 sendDetachedInventory(name, client->peer_id);
4586         }
4587 }
4588
4589 void Server::sendDetachedInventories(u16 peer_id)
4590 {
4591         DSTACK(__FUNCTION_NAME);
4592
4593         for(std::map<std::string, Inventory*>::iterator
4594                         i = m_detached_inventories.begin();
4595                         i != m_detached_inventories.end(); i++){
4596                 const std::string &name = i->first;
4597                 //Inventory *inv = i->second;
4598                 sendDetachedInventory(name, peer_id);
4599         }
4600 }
4601
4602 /*
4603         Something random
4604 */
4605
4606 void Server::DiePlayer(u16 peer_id)
4607 {
4608         DSTACK(__FUNCTION_NAME);
4609
4610         PlayerSAO *playersao = getPlayerSAO(peer_id);
4611         assert(playersao);
4612
4613         infostream<<"Server::DiePlayer(): Player "
4614                         <<playersao->getPlayer()->getName()
4615                         <<" dies"<<std::endl;
4616
4617         playersao->setHP(0);
4618
4619         // Trigger scripted stuff
4620         m_script->on_dieplayer(playersao);
4621
4622         SendPlayerHP(peer_id);
4623         SendDeathscreen(m_con, peer_id, false, v3f(0,0,0));
4624 }
4625
4626 void Server::RespawnPlayer(u16 peer_id)
4627 {
4628         DSTACK(__FUNCTION_NAME);
4629
4630         PlayerSAO *playersao = getPlayerSAO(peer_id);
4631         assert(playersao);
4632
4633         infostream<<"Server::RespawnPlayer(): Player "
4634                         <<playersao->getPlayer()->getName()
4635                         <<" respawns"<<std::endl;
4636
4637         playersao->setHP(PLAYER_MAX_HP);
4638
4639         bool repositioned = m_script->on_respawnplayer(playersao);
4640         if(!repositioned){
4641                 v3f pos = findSpawnPos(m_env->getServerMap());
4642                 playersao->setPos(pos);
4643         }
4644 }
4645
4646 void Server::DenyAccess(u16 peer_id, const std::wstring &reason)
4647 {
4648         DSTACK(__FUNCTION_NAME);
4649
4650         SendAccessDenied(m_con, peer_id, reason);
4651
4652         RemoteClient *client = getClientNoEx(peer_id);
4653         if(client)
4654                 client->denied = true;
4655
4656         // If there are way too many clients, get rid of denied new ones immediately
4657         if((int)m_clients.size() > 2 * g_settings->getU16("max_users")){
4658                 verbosestream<<"Server: DenyAccess: Too many clients; getting rid of "
4659                                 <<"peer_id="<<peer_id<<" immediately"<<std::endl;
4660                 // Delete peer to stop sending it data
4661                 m_con.DeletePeer(peer_id);
4662                 // Delete client also to stop block sends and other stuff
4663                 DeleteClient(peer_id, CDR_DENY);
4664         }
4665 }
4666
4667 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
4668 {
4669         DSTACK(__FUNCTION_NAME);
4670
4671         // Error check
4672         std::map<u16, RemoteClient*>::iterator n;
4673         n = m_clients.find(peer_id);
4674         // The client may not exist; clients are immediately removed if their
4675         // access is denied, and this event occurs later then.
4676         if(n == m_clients.end())
4677                 return;
4678
4679         /*
4680                 Mark objects to be not known by the client
4681         */
4682         RemoteClient *client = n->second;
4683         // Handle objects
4684         for(std::set<u16>::iterator
4685                         i = client->m_known_objects.begin();
4686                         i != client->m_known_objects.end(); ++i)
4687         {
4688                 // Get object
4689                 u16 id = *i;
4690                 ServerActiveObject* obj = m_env->getActiveObject(id);
4691
4692                 if(obj && obj->m_known_by_count > 0)
4693                         obj->m_known_by_count--;
4694         }
4695
4696         /*
4697                 Clear references to playing sounds
4698         */
4699         for(std::map<s32, ServerPlayingSound>::iterator
4700                         i = m_playing_sounds.begin();
4701                         i != m_playing_sounds.end();)
4702         {
4703                 ServerPlayingSound &psound = i->second;
4704                 psound.clients.erase(peer_id);
4705                 if(psound.clients.size() == 0)
4706                         m_playing_sounds.erase(i++);
4707                 else
4708                         i++;
4709         }
4710
4711         Player *player = m_env->getPlayer(peer_id);
4712
4713         // Collect information about leaving in chat
4714         std::wstring message;
4715         {
4716                 if(player != NULL && reason != CDR_DENY)
4717                 {
4718                         std::wstring name = narrow_to_wide(player->getName());
4719                         message += L"*** ";
4720                         message += name;
4721                         message += L" left the game.";
4722                         if(reason == CDR_TIMEOUT)
4723                                 message += L" (timed out)";
4724                 }
4725         }
4726
4727         /* Run scripts and remove from environment */
4728         {
4729                 if(player != NULL)
4730                 {
4731                         PlayerSAO *playersao = player->getPlayerSAO();
4732                         assert(playersao);
4733
4734                         m_script->on_leaveplayer(playersao);
4735
4736                         playersao->disconnected();
4737                 }
4738         }
4739
4740         /*
4741                 Print out action
4742         */
4743         {
4744                 if(player != NULL && reason != CDR_DENY)
4745                 {
4746                         std::ostringstream os(std::ios_base::binary);
4747                         for(std::map<u16, RemoteClient*>::iterator
4748                                 i = m_clients.begin();
4749                                 i != m_clients.end(); ++i)
4750                         {
4751                                 RemoteClient *client = i->second;
4752                                 assert(client->peer_id == i->first);
4753                                 if(client->serialization_version == SER_FMT_VER_INVALID)
4754                                         continue;
4755                                 // Get player
4756                                 Player *player = m_env->getPlayer(client->peer_id);
4757                                 if(!player)
4758                                         continue;
4759                                 // Get name of player
4760                                 os<<player->getName()<<" ";
4761                         }
4762
4763                         actionstream<<player->getName()<<" "
4764                                         <<(reason==CDR_TIMEOUT?"times out.":"leaves game.")
4765                                         <<" List of players: "<<os.str()<<std::endl;
4766                 }
4767         }
4768
4769         // Delete client
4770         delete m_clients[peer_id];
4771         m_clients.erase(peer_id);
4772
4773         // Send leave chat message to all remaining clients
4774         if(message.length() != 0)
4775                 BroadcastChatMessage(message);
4776 }
4777
4778 void Server::UpdateCrafting(u16 peer_id)
4779 {
4780         DSTACK(__FUNCTION_NAME);
4781
4782         Player* player = m_env->getPlayer(peer_id);
4783         assert(player);
4784
4785         // Get a preview for crafting
4786         ItemStack preview;
4787         InventoryLocation loc;
4788         loc.setPlayer(player->getName());
4789         getCraftingResult(&player->inventory, preview, false, this);
4790         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
4791
4792         // Put the new preview in
4793         InventoryList *plist = player->inventory.getList("craftpreview");
4794         assert(plist);
4795         assert(plist->getSize() >= 1);
4796         plist->changeItem(0, preview);
4797 }
4798
4799 RemoteClient* Server::getClient(u16 peer_id)
4800 {
4801         RemoteClient *client = getClientNoEx(peer_id);
4802         if(!client)
4803                 throw ClientNotFoundException("Client not found");
4804         return client;
4805 }
4806 RemoteClient* Server::getClientNoEx(u16 peer_id)
4807 {
4808         std::map<u16, RemoteClient*>::iterator n;
4809         n = m_clients.find(peer_id);
4810         // The client may not exist; clients are immediately removed if their
4811         // access is denied, and this event occurs later then.
4812         if(n == m_clients.end())
4813                 return NULL;
4814         return n->second;
4815 }
4816
4817 std::string Server::getPlayerName(u16 peer_id)
4818 {
4819         Player *player = m_env->getPlayer(peer_id);
4820         if(player == NULL)
4821                 return "[id="+itos(peer_id)+"]";
4822         return player->getName();
4823 }
4824
4825 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
4826 {
4827         Player *player = m_env->getPlayer(peer_id);
4828         if(player == NULL)
4829                 return NULL;
4830         return player->getPlayerSAO();
4831 }
4832
4833 std::wstring Server::getStatusString()
4834 {
4835         std::wostringstream os(std::ios_base::binary);
4836         os<<L"# Server: ";
4837         // Version
4838         os<<L"version="<<narrow_to_wide(minetest_version_simple);
4839         // Uptime
4840         os<<L", uptime="<<m_uptime.get();
4841         // Max lag estimate
4842         os<<L", max_lag="<<m_env->getMaxLagEstimate();
4843         // Information about clients
4844         std::map<u16, RemoteClient*>::iterator i;
4845         bool first;
4846         os<<L", clients={";
4847         for(i = m_clients.begin(), first = true;
4848                 i != m_clients.end(); ++i)
4849         {
4850                 // Get client and check that it is valid
4851                 RemoteClient *client = i->second;
4852                 assert(client->peer_id == i->first);
4853                 if(client->serialization_version == SER_FMT_VER_INVALID)
4854                         continue;
4855                 // Get player
4856                 Player *player = m_env->getPlayer(client->peer_id);
4857                 // Get name of player
4858                 std::wstring name = L"unknown";
4859                 if(player != NULL)
4860                         name = narrow_to_wide(player->getName());
4861                 // Add name to information string
4862                 if(!first)
4863                         os<<L",";
4864                 else
4865                         first = false;
4866                 os<<name;
4867         }
4868         os<<L"}";
4869         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
4870                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
4871         if(g_settings->get("motd") != "")
4872                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
4873         return os.str();
4874 }
4875
4876 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
4877 {
4878         std::set<std::string> privs;
4879         m_script->getAuth(name, NULL, &privs);
4880         return privs;
4881 }
4882
4883 bool Server::checkPriv(const std::string &name, const std::string &priv)
4884 {
4885         std::set<std::string> privs = getPlayerEffectivePrivs(name);
4886         return (privs.count(priv) != 0);
4887 }
4888
4889 void Server::reportPrivsModified(const std::string &name)
4890 {
4891         if(name == ""){
4892                 for(std::map<u16, RemoteClient*>::iterator
4893                                 i = m_clients.begin();
4894                                 i != m_clients.end(); ++i){
4895                         RemoteClient *client = i->second;
4896                         Player *player = m_env->getPlayer(client->peer_id);
4897                         reportPrivsModified(player->getName());
4898                 }
4899         } else {
4900                 Player *player = m_env->getPlayer(name.c_str());
4901                 if(!player)
4902                         return;
4903                 SendPlayerPrivileges(player->peer_id);
4904                 PlayerSAO *sao = player->getPlayerSAO();
4905                 if(!sao)
4906                         return;
4907                 sao->updatePrivileges(
4908                                 getPlayerEffectivePrivs(name),
4909                                 isSingleplayer());
4910         }
4911 }
4912
4913 void Server::reportInventoryFormspecModified(const std::string &name)
4914 {
4915         Player *player = m_env->getPlayer(name.c_str());
4916         if(!player)
4917                 return;
4918         SendPlayerInventoryFormspec(player->peer_id);
4919 }
4920
4921 void Server::setIpBanned(const std::string &ip, const std::string &name)
4922 {
4923         m_banmanager->add(ip, name);
4924 }
4925
4926 void Server::unsetIpBanned(const std::string &ip_or_name)
4927 {
4928         m_banmanager->remove(ip_or_name);
4929 }
4930
4931 std::string Server::getBanDescription(const std::string &ip_or_name)
4932 {
4933         return m_banmanager->getBanDescription(ip_or_name);
4934 }
4935
4936 void Server::notifyPlayer(const char *name, const std::wstring msg, const bool prepend = true)
4937 {
4938         Player *player = m_env->getPlayer(name);
4939         if(!player)
4940                 return;
4941         if (prepend)
4942                 SendChatMessage(player->peer_id, std::wstring(L"Server -!- ")+msg);
4943         else
4944                 SendChatMessage(player->peer_id, msg);
4945 }
4946
4947 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
4948 {
4949         Player *player = m_env->getPlayer(playername);
4950
4951         if(!player)
4952         {
4953                 infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
4954                 return false;
4955         }
4956
4957         SendShowFormspecMessage(player->peer_id, formspec, formname);
4958         return true;
4959 }
4960
4961 u32 Server::hudAdd(Player *player, HudElement *form) {
4962         if (!player)
4963                 return -1;
4964
4965         u32 id = player->getFreeHudID();
4966         if (id < player->hud.size())
4967                 player->hud[id] = form;
4968         else
4969                 player->hud.push_back(form);
4970         
4971         SendHUDAdd(player->peer_id, id, form);
4972         return id;
4973 }
4974
4975 bool Server::hudRemove(Player *player, u32 id) {
4976         if (!player || id >= player->hud.size() || !player->hud[id])
4977                 return false;
4978
4979         delete player->hud[id];
4980         player->hud[id] = NULL;
4981         
4982         SendHUDRemove(player->peer_id, id);
4983         return true;
4984 }
4985
4986 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
4987         if (!player)
4988                 return false;
4989
4990         SendHUDChange(player->peer_id, id, stat, data);
4991         return true;
4992 }
4993
4994 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
4995         if (!player)
4996                 return false;
4997
4998         SendHUDSetFlags(player->peer_id, flags, mask);
4999         return true;
5000 }
5001
5002 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
5003         if (!player)
5004                 return false;
5005         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
5006                 return false;
5007
5008         std::ostringstream os(std::ios::binary);
5009         writeS32(os, hotbar_itemcount);
5010         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
5011         return true;
5012 }
5013
5014 void Server::hudSetHotbarImage(Player *player, std::string name) {
5015         if (!player)
5016                 return;
5017
5018         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
5019 }
5020
5021 void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
5022         if (!player)
5023                 return;
5024
5025         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
5026 }
5027
5028 void Server::notifyPlayers(const std::wstring msg)
5029 {
5030         BroadcastChatMessage(msg);
5031 }
5032
5033 void Server::spawnParticle(const char *playername, v3f pos,
5034                 v3f velocity, v3f acceleration,
5035                 float expirationtime, float size, bool
5036                 collisiondetection, std::string texture)
5037 {
5038         Player *player = m_env->getPlayer(playername);
5039         if(!player)
5040                 return;
5041         SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
5042                         expirationtime, size, collisiondetection, texture);
5043 }
5044
5045 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
5046                 float expirationtime, float size,
5047                 bool collisiondetection, std::string texture)
5048 {
5049         SendSpawnParticleAll(pos, velocity, acceleration,
5050                         expirationtime, size, collisiondetection, texture);
5051 }
5052
5053 u32 Server::addParticleSpawner(const char *playername,
5054                 u16 amount, float spawntime,
5055                 v3f minpos, v3f maxpos,
5056                 v3f minvel, v3f maxvel,
5057                 v3f minacc, v3f maxacc,
5058                 float minexptime, float maxexptime,
5059                 float minsize, float maxsize,
5060                 bool collisiondetection, std::string texture)
5061 {
5062         Player *player = m_env->getPlayer(playername);
5063         if(!player)
5064                 return -1;
5065
5066         u32 id = 0;
5067         for(;;) // look for unused particlespawner id
5068         {
5069                 id++;
5070                 if (std::find(m_particlespawner_ids.begin(),
5071                                 m_particlespawner_ids.end(), id)
5072                                 == m_particlespawner_ids.end())
5073                 {
5074                         m_particlespawner_ids.push_back(id);
5075                         break;
5076                 }
5077         }
5078
5079         SendAddParticleSpawner(player->peer_id, amount, spawntime,
5080                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
5081                 minexptime, maxexptime, minsize, maxsize,
5082                 collisiondetection, texture, id);
5083
5084         return id;
5085 }
5086
5087 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
5088                 v3f minpos, v3f maxpos,
5089                 v3f minvel, v3f maxvel,
5090                 v3f minacc, v3f maxacc,
5091                 float minexptime, float maxexptime,
5092                 float minsize, float maxsize,
5093                 bool collisiondetection, std::string texture)
5094 {
5095         u32 id = 0;
5096         for(;;) // look for unused particlespawner id
5097         {
5098                 id++;
5099                 if (std::find(m_particlespawner_ids.begin(),
5100                                 m_particlespawner_ids.end(), id)
5101                                 == m_particlespawner_ids.end())
5102                 {
5103                         m_particlespawner_ids.push_back(id);
5104                         break;
5105                 }
5106         }
5107
5108         SendAddParticleSpawnerAll(amount, spawntime,
5109                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
5110                 minexptime, maxexptime, minsize, maxsize,
5111                 collisiondetection, texture, id);
5112
5113         return id;
5114 }
5115
5116 void Server::deleteParticleSpawner(const char *playername, u32 id)
5117 {
5118         Player *player = m_env->getPlayer(playername);
5119         if(!player)
5120                 return;
5121
5122         m_particlespawner_ids.erase(
5123                         std::remove(m_particlespawner_ids.begin(),
5124                         m_particlespawner_ids.end(), id),
5125                         m_particlespawner_ids.end());
5126         SendDeleteParticleSpawner(player->peer_id, id);
5127 }
5128
5129 void Server::deleteParticleSpawnerAll(u32 id)
5130 {
5131         m_particlespawner_ids.erase(
5132                         std::remove(m_particlespawner_ids.begin(),
5133                         m_particlespawner_ids.end(), id),
5134                         m_particlespawner_ids.end());
5135         SendDeleteParticleSpawnerAll(id);
5136 }
5137
5138 Inventory* Server::createDetachedInventory(const std::string &name)
5139 {
5140         if(m_detached_inventories.count(name) > 0){
5141                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
5142                 delete m_detached_inventories[name];
5143         } else {
5144                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
5145         }
5146         Inventory *inv = new Inventory(m_itemdef);
5147         assert(inv);
5148         m_detached_inventories[name] = inv;
5149         sendDetachedInventoryToAll(name);
5150         return inv;
5151 }
5152
5153 class BoolScopeSet
5154 {
5155 public:
5156         BoolScopeSet(bool *dst, bool val):
5157                 m_dst(dst)
5158         {
5159                 m_orig_state = *m_dst;
5160                 *m_dst = val;
5161         }
5162         ~BoolScopeSet()
5163         {
5164                 *m_dst = m_orig_state;
5165         }
5166 private:
5167         bool *m_dst;
5168         bool m_orig_state;
5169 };
5170
5171 // actions: time-reversed list
5172 // Return value: success/failure
5173 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
5174                 std::list<std::string> *log)
5175 {
5176         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
5177         ServerMap *map = (ServerMap*)(&m_env->getMap());
5178         // Disable rollback report sink while reverting
5179         BoolScopeSet rollback_scope_disable(&m_rollback_sink_enabled, false);
5180
5181         // Fail if no actions to handle
5182         if(actions.empty()){
5183                 log->push_back("Nothing to do.");
5184                 return false;
5185         }
5186
5187         int num_tried = 0;
5188         int num_failed = 0;
5189
5190         for(std::list<RollbackAction>::const_iterator
5191                         i = actions.begin();
5192                         i != actions.end(); i++)
5193         {
5194                 const RollbackAction &action = *i;
5195                 num_tried++;
5196                 bool success = action.applyRevert(map, this, this);
5197                 if(!success){
5198                         num_failed++;
5199                         std::ostringstream os;
5200                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
5201                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
5202                         if(log)
5203                                 log->push_back(os.str());
5204                 }else{
5205                         std::ostringstream os;
5206                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
5207                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
5208                         if(log)
5209                                 log->push_back(os.str());
5210                 }
5211         }
5212
5213         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
5214                         <<" failed"<<std::endl;
5215
5216         // Call it done if less than half failed
5217         return num_failed <= num_tried/2;
5218 }
5219
5220 // IGameDef interface
5221 // Under envlock
5222 IItemDefManager* Server::getItemDefManager()
5223 {
5224         return m_itemdef;
5225 }
5226 INodeDefManager* Server::getNodeDefManager()
5227 {
5228         return m_nodedef;
5229 }
5230 ICraftDefManager* Server::getCraftDefManager()
5231 {
5232         return m_craftdef;
5233 }
5234 ITextureSource* Server::getTextureSource()
5235 {
5236         return NULL;
5237 }
5238 IShaderSource* Server::getShaderSource()
5239 {
5240         return NULL;
5241 }
5242 u16 Server::allocateUnknownNodeId(const std::string &name)
5243 {
5244         return m_nodedef->allocateDummy(name);
5245 }
5246 ISoundManager* Server::getSoundManager()
5247 {
5248         return &dummySoundManager;
5249 }
5250 MtEventManager* Server::getEventManager()
5251 {
5252         return m_event;
5253 }
5254 IRollbackReportSink* Server::getRollbackReportSink()
5255 {
5256         if(!m_enable_rollback_recording)
5257                 return NULL;
5258         if(!m_rollback_sink_enabled)
5259                 return NULL;
5260         return m_rollback;
5261 }
5262
5263 IWritableItemDefManager* Server::getWritableItemDefManager()
5264 {
5265         return m_itemdef;
5266 }
5267 IWritableNodeDefManager* Server::getWritableNodeDefManager()
5268 {
5269         return m_nodedef;
5270 }
5271 IWritableCraftDefManager* Server::getWritableCraftDefManager()
5272 {
5273         return m_craftdef;
5274 }
5275
5276 const ModSpec* Server::getModSpec(const std::string &modname)
5277 {
5278         for(std::vector<ModSpec>::iterator i = m_mods.begin();
5279                         i != m_mods.end(); i++){
5280                 const ModSpec &mod = *i;
5281                 if(mod.name == modname)
5282                         return &mod;
5283         }
5284         return NULL;
5285 }
5286 void Server::getModNames(std::list<std::string> &modlist)
5287 {
5288         for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++)
5289         {
5290                 modlist.push_back(i->name);
5291         }
5292 }
5293 std::string Server::getBuiltinLuaPath()
5294 {
5295         return porting::path_share + DIR_DELIM + "builtin";
5296 }
5297
5298 v3f findSpawnPos(ServerMap &map)
5299 {
5300         //return v3f(50,50,50)*BS;
5301
5302         v3s16 nodepos;
5303
5304 #if 0
5305         nodepos = v2s16(0,0);
5306         groundheight = 20;
5307 #endif
5308
5309 #if 1
5310         s16 water_level = map.m_mgparams->water_level;
5311
5312         // Try to find a good place a few times
5313         for(s32 i=0; i<1000; i++)
5314         {
5315                 s32 range = 1 + i;
5316                 // We're going to try to throw the player to this position
5317                 v2s16 nodepos2d = v2s16(
5318                                 -range + (myrand() % (range * 2)),
5319                                 -range + (myrand() % (range * 2)));
5320
5321                 // Get ground height at point
5322                 s16 groundheight = map.findGroundLevel(nodepos2d, g_settings->getBool("cache_block_before_spawn"));
5323                 if (groundheight <= water_level) // Don't go underwater
5324                         continue;
5325                 if (groundheight > water_level + g_settings->getS16("max_spawn_height")) // Don't go to high places
5326                         continue;
5327
5328                 nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
5329                 bool is_good = false;
5330                 s32 air_count = 0;
5331                 for (s32 i = 0; i < 10; i++) {
5332                         v3s16 blockpos = getNodeBlockPos(nodepos);
5333                         map.emergeBlock(blockpos, true);
5334                         content_t c = map.getNodeNoEx(nodepos).getContent();
5335                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
5336                                 air_count++;
5337                                 if (air_count >= 2){
5338                                         is_good = true;
5339                                         break;
5340                                 }
5341                         }
5342                         nodepos.Y++;
5343                 }
5344                 if(is_good){
5345                         // Found a good place
5346                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
5347                         break;
5348                 }
5349         }
5350 #endif
5351
5352         return intToFloat(nodepos, BS);
5353 }
5354
5355 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
5356 {
5357         RemotePlayer *player = NULL;
5358         bool newplayer = false;
5359
5360         /*
5361                 Try to get an existing player
5362         */
5363         player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
5364
5365         // If player is already connected, cancel
5366         if(player != NULL && player->peer_id != 0)
5367         {
5368                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
5369                 return NULL;
5370         }
5371
5372         /*
5373                 If player with the wanted peer_id already exists, cancel.
5374         */
5375         if(m_env->getPlayer(peer_id) != NULL)
5376         {
5377                 infostream<<"emergePlayer(): Player with wrong name but same"
5378                                 " peer_id already exists"<<std::endl;
5379                 return NULL;
5380         }
5381
5382         /*
5383                 Create a new player if it doesn't exist yet
5384         */
5385         if(player == NULL)
5386         {
5387                 newplayer = true;
5388                 player = new RemotePlayer(this);
5389                 player->updateName(name);
5390
5391                 /* Set player position */
5392                 infostream<<"Server: Finding spawn place for player \""
5393                                 <<name<<"\""<<std::endl;
5394                 v3f pos = findSpawnPos(m_env->getServerMap());
5395                 player->setPosition(pos);
5396
5397                 /* Add player to environment */
5398                 m_env->addPlayer(player);
5399         }
5400
5401         /*
5402                 Create a new player active object
5403         */
5404         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
5405                         getPlayerEffectivePrivs(player->getName()),
5406                         isSingleplayer());
5407
5408         /* Clean up old HUD elements from previous sessions */
5409         player->hud.clear();
5410
5411         /* Add object to environment */
5412         m_env->addActiveObject(playersao);
5413
5414         /* Run scripts */
5415         if(newplayer)
5416                 m_script->on_newplayer(playersao);
5417
5418         m_script->on_joinplayer(playersao);
5419
5420         return playersao;
5421 }
5422
5423 void Server::handlePeerChange(PeerChange &c)
5424 {
5425         JMutexAutoLock envlock(m_env_mutex);
5426         JMutexAutoLock conlock(m_con_mutex);
5427
5428         if(c.type == PEER_ADDED)
5429         {
5430                 /*
5431                         Add
5432                 */
5433
5434                 // Error check
5435                 std::map<u16, RemoteClient*>::iterator n;
5436                 n = m_clients.find(c.peer_id);
5437                 // The client shouldn't already exist
5438                 assert(n == m_clients.end());
5439
5440                 // Create client
5441                 RemoteClient *client = new RemoteClient();
5442                 client->peer_id = c.peer_id;
5443                 m_clients[client->peer_id] = client;
5444
5445         } // PEER_ADDED
5446         else if(c.type == PEER_REMOVED)
5447         {
5448                 /*
5449                         Delete
5450                 */
5451
5452                 DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
5453
5454         } // PEER_REMOVED
5455         else
5456         {
5457                 assert(0);
5458         }
5459 }
5460
5461 void Server::handlePeerChanges()
5462 {
5463         while(m_peer_change_queue.size() > 0)
5464         {
5465                 PeerChange c = m_peer_change_queue.pop_front();
5466
5467                 verbosestream<<"Server: Handling peer change: "
5468                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
5469                                 <<std::endl;
5470
5471                 handlePeerChange(c);
5472         }
5473 }
5474
5475 void dedicated_server_loop(Server &server, bool &kill)
5476 {
5477         DSTACK(__FUNCTION_NAME);
5478
5479         verbosestream<<"dedicated_server_loop()"<<std::endl;
5480
5481         IntervalLimiter m_profiler_interval;
5482
5483         for(;;)
5484         {
5485                 float steplen = g_settings->getFloat("dedicated_server_step");
5486                 // This is kind of a hack but can be done like this
5487                 // because server.step() is very light
5488                 {
5489                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
5490                         sleep_ms((int)(steplen*1000.0));
5491                 }
5492                 server.step(steplen);
5493
5494                 if(server.getShutdownRequested() || kill)
5495                 {
5496                         infostream<<"Dedicated server quitting"<<std::endl;
5497 #if USE_CURL
5498                         if(g_settings->getBool("server_announce") == true)
5499                                 ServerList::sendAnnounce("delete");
5500 #endif
5501                         break;
5502                 }
5503
5504                 /*
5505                         Profiler
5506                 */
5507                 float profiler_print_interval =
5508                                 g_settings->getFloat("profiler_print_interval");
5509                 if(profiler_print_interval != 0)
5510                 {
5511                         if(m_profiler_interval.step(steplen, profiler_print_interval))
5512                         {
5513                                 infostream<<"Profiler:"<<std::endl;
5514                                 g_profiler->print(infostream);
5515                                 g_profiler->clear();
5516                         }
5517                 }
5518         }
5519 }
5520
5521