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