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