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