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