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