]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Add support for IPv6
[dragonfireclient.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "clientserver.h"
25 #include "map.h"
26 #include "jmutexautolock.h"
27 #include "main.h"
28 #include "constants.h"
29 #include "voxel.h"
30 #include "config.h"
31 #include "filesys.h"
32 #include "mapblock.h"
33 #include "serverobject.h"
34 #include "settings.h"
35 #include "profiler.h"
36 #include "log.h"
37 #include "script/cpp_api/scriptapi.h"
38 #include "nodedef.h"
39 #include "itemdef.h"
40 #include "craftdef.h"
41 #include "emerge.h"
42 #include "mapgen.h"
43 #include "biome.h"
44 #include "content_mapnode.h"
45 #include "content_nodemeta.h"
46 #include "content_abm.h"
47 #include "content_sao.h"
48 #include "mods.h"
49 #include "sha1.h"
50 #include "base64.h"
51 #include "tool.h"
52 #include "sound.h" // dummySoundManager
53 #include "event_manager.h"
54 #include "hex.h"
55 #include "serverlist.h"
56 #include "util/string.h"
57 #include "util/pointedthing.h"
58 #include "util/mathconstants.h"
59 #include "rollback.h"
60 #include "util/serialize.h"
61 #include "defaultsettings.h"
62
63 void * ServerThread::Thread()
64 {
65         ThreadStarted();
66
67         log_register_thread("ServerThread");
68
69         DSTACK(__FUNCTION_NAME);
70
71         BEGIN_DEBUG_EXCEPTION_HANDLER
72
73         while(getRun())
74         {
75                 try{
76                         //TimeTaker timer("AsyncRunStep() + Receive()");
77
78                         {
79                                 //TimeTaker timer("AsyncRunStep()");
80                                 m_server->AsyncRunStep();
81                         }
82
83                         //infostream<<"Running m_server->Receive()"<<std::endl;
84                         m_server->Receive();
85                 }
86                 catch(con::NoIncomingDataException &e)
87                 {
88                 }
89                 catch(con::PeerNotFoundException &e)
90                 {
91                         infostream<<"Server: PeerNotFoundException"<<std::endl;
92                 }
93                 catch(con::ConnectionBindFailed &e)
94                 {
95                         m_server->setAsyncFatalError(e.what());
96                 }
97                 catch(LuaError &e)
98                 {
99                         m_server->setAsyncFatalError(e.what());
100                 }
101         }
102
103         END_DEBUG_EXCEPTION_HANDLER(errorstream)
104
105         return NULL;
106 }
107
108 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
109 {
110         if(pos_exists) *pos_exists = false;
111         switch(type){
112         case SSP_LOCAL:
113                 return v3f(0,0,0);
114         case SSP_POSITIONAL:
115                 if(pos_exists) *pos_exists = true;
116                 return pos;
117         case SSP_OBJECT: {
118                 if(object == 0)
119                         return v3f(0,0,0);
120                 ServerActiveObject *sao = env->getActiveObject(object);
121                 if(!sao)
122                         return v3f(0,0,0);
123                 if(pos_exists) *pos_exists = true;
124                 return sao->getBasePosition(); }
125         }
126         return v3f(0,0,0);
127 }
128
129 void RemoteClient::GetNextBlocks(Server *server, float dtime,
130                 std::vector<PrioritySortedBlockTransfer> &dest)
131 {
132         DSTACK(__FUNCTION_NAME);
133
134         /*u32 timer_result;
135         TimeTaker timer("RemoteClient::GetNextBlocks", &timer_result);*/
136
137         // Increment timers
138         m_nothing_to_send_pause_timer -= dtime;
139         m_nearest_unsent_reset_timer += dtime;
140
141         if(m_nothing_to_send_pause_timer >= 0)
142                 return;
143
144         Player *player = server->m_env->getPlayer(peer_id);
145         // This can happen sometimes; clients and players are not in perfect sync.
146         if(player == NULL)
147                 return;
148
149         // Won't send anything if already sending
150         if(m_blocks_sending.size() >= g_settings->getU16
151                         ("max_simultaneous_block_sends_per_client"))
152         {
153                 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
154                 return;
155         }
156
157         //TimeTaker timer("RemoteClient::GetNextBlocks");
158
159         v3f playerpos = player->getPosition();
160         v3f playerspeed = player->getSpeed();
161         v3f playerspeeddir(0,0,0);
162         if(playerspeed.getLength() > 1.0*BS)
163                 playerspeeddir = playerspeed / playerspeed.getLength();
164         // Predict to next block
165         v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
166
167         v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
168
169         v3s16 center = getNodeBlockPos(center_nodepos);
170
171         // Camera position and direction
172         v3f camera_pos = player->getEyePosition();
173         v3f camera_dir = v3f(0,0,1);
174         camera_dir.rotateYZBy(player->getPitch());
175         camera_dir.rotateXZBy(player->getYaw());
176
177         /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
178                         <<camera_dir.Z<<")"<<std::endl;*/
179
180         /*
181                 Get the starting value of the block finder radius.
182         */
183
184         if(m_last_center != center)
185         {
186                 m_nearest_unsent_d = 0;
187                 m_last_center = center;
188         }
189
190         /*infostream<<"m_nearest_unsent_reset_timer="
191                         <<m_nearest_unsent_reset_timer<<std::endl;*/
192
193         // Reset periodically to workaround for some bugs or stuff
194         if(m_nearest_unsent_reset_timer > 20.0)
195         {
196                 m_nearest_unsent_reset_timer = 0;
197                 m_nearest_unsent_d = 0;
198                 //infostream<<"Resetting m_nearest_unsent_d for "
199                 //              <<server->getPlayerName(peer_id)<<std::endl;
200         }
201
202         //s16 last_nearest_unsent_d = m_nearest_unsent_d;
203         s16 d_start = m_nearest_unsent_d;
204
205         //infostream<<"d_start="<<d_start<<std::endl;
206
207         u16 max_simul_sends_setting = g_settings->getU16
208                         ("max_simultaneous_block_sends_per_client");
209         u16 max_simul_sends_usually = max_simul_sends_setting;
210
211         /*
212                 Check the time from last addNode/removeNode.
213
214                 Decrease send rate if player is building stuff.
215         */
216         m_time_from_building += dtime;
217         if(m_time_from_building < g_settings->getFloat(
218                                 "full_block_send_enable_min_time_from_building"))
219         {
220                 max_simul_sends_usually
221                         = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
222         }
223
224         /*
225                 Number of blocks sending + number of blocks selected for sending
226         */
227         u32 num_blocks_selected = m_blocks_sending.size();
228
229         /*
230                 next time d will be continued from the d from which the nearest
231                 unsent block was found this time.
232
233                 This is because not necessarily any of the blocks found this
234                 time are actually sent.
235         */
236         s32 new_nearest_unsent_d = -1;
237
238         s16 d_max = g_settings->getS16("max_block_send_distance");
239         s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
240
241         // Don't loop very much at a time
242         s16 max_d_increment_at_time = 2;
243         if(d_max > d_start + max_d_increment_at_time)
244                 d_max = d_start + max_d_increment_at_time;
245         /*if(d_max_gen > d_start+2)
246                 d_max_gen = d_start+2;*/
247
248         //infostream<<"Starting from "<<d_start<<std::endl;
249
250         s32 nearest_emerged_d = -1;
251         s32 nearest_emergefull_d = -1;
252         s32 nearest_sent_d = -1;
253         bool queue_is_full = false;
254
255         s16 d;
256         for(d = d_start; d <= d_max; d++)
257         {
258                 /*errorstream<<"checking d="<<d<<" for "
259                                 <<server->getPlayerName(peer_id)<<std::endl;*/
260                 //infostream<<"RemoteClient::SendBlocks(): d="<<d<<std::endl;
261
262                 /*
263                         If m_nearest_unsent_d was changed by the EmergeThread
264                         (it can change it to 0 through SetBlockNotSent),
265                         update our d to it.
266                         Else update m_nearest_unsent_d
267                 */
268                 /*if(m_nearest_unsent_d != last_nearest_unsent_d)
269                 {
270                         d = m_nearest_unsent_d;
271                         last_nearest_unsent_d = m_nearest_unsent_d;
272                 }*/
273
274                 /*
275                         Get the border/face dot coordinates of a "d-radiused"
276                         box
277                 */
278                 std::list<v3s16> list;
279                 getFacePositions(list, d);
280
281                 std::list<v3s16>::iterator li;
282                 for(li=list.begin(); li!=list.end(); ++li)
283                 {
284                         v3s16 p = *li + center;
285
286                         /*
287                                 Send throttling
288                                 - Don't allow too many simultaneous transfers
289                                 - EXCEPT when the blocks are very close
290
291                                 Also, don't send blocks that are already flying.
292                         */
293
294                         // Start with the usual maximum
295                         u16 max_simul_dynamic = max_simul_sends_usually;
296
297                         // If block is very close, allow full maximum
298                         if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
299                                 max_simul_dynamic = max_simul_sends_setting;
300
301                         // Don't select too many blocks for sending
302                         if(num_blocks_selected >= max_simul_dynamic)
303                         {
304                                 queue_is_full = true;
305                                 goto queue_full_break;
306                         }
307
308                         // Don't send blocks that are currently being transferred
309                         if(m_blocks_sending.find(p) != m_blocks_sending.end())
310                                 continue;
311
312                         /*
313                                 Do not go over-limit
314                         */
315                         if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
316                         || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
317                         || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
318                         || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
319                         || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
320                         || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
321                                 continue;
322
323                         // If this is true, inexistent block will be made from scratch
324                         bool generate = d <= d_max_gen;
325
326                         {
327                                 /*// Limit the generating area vertically to 2/3
328                                 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
329                                         generate = false;*/
330
331                                 // Limit the send area vertically to 1/2
332                                 if(abs(p.Y - center.Y) > d_max / 2)
333                                         continue;
334                         }
335
336 #if 0
337                         /*
338                                 If block is far away, don't generate it unless it is
339                                 near ground level.
340                         */
341                         if(d >= 4)
342                         {
343         #if 1
344                                 // Block center y in nodes
345                                 f32 y = (f32)(p.Y * MAP_BLOCKSIZE + MAP_BLOCKSIZE/2);
346                                 // Don't generate if it's very high or very low
347                                 if(y < -64 || y > 64)
348                                         generate = false;
349         #endif
350         #if 0
351                                 v2s16 p2d_nodes_center(
352                                         MAP_BLOCKSIZE*p.X,
353                                         MAP_BLOCKSIZE*p.Z);
354
355                                 // Get ground height in nodes
356                                 s16 gh = server->m_env->getServerMap().findGroundLevel(
357                                                 p2d_nodes_center);
358
359                                 // If differs a lot, don't generate
360                                 if(fabs(gh - y) > MAP_BLOCKSIZE*2)
361                                         generate = false;
362                                         // Actually, don't even send it
363                                         //continue;
364         #endif
365                         }
366 #endif
367
368                         //infostream<<"d="<<d<<std::endl;
369 #if 1
370                         /*
371                                 Don't generate or send if not in sight
372                                 FIXME This only works if the client uses a small enough
373                                 FOV setting. The default of 72 degrees is fine.
374                         */
375
376                         float camera_fov = (72.0*M_PI/180) * 4./3.;
377                         if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
378                         {
379                                 continue;
380                         }
381 #endif
382                         /*
383                                 Don't send already sent blocks
384                         */
385                         {
386                                 if(m_blocks_sent.find(p) != m_blocks_sent.end())
387                                 {
388                                         continue;
389                                 }
390                         }
391
392                         /*
393                                 Check if map has this block
394                         */
395                         MapBlock *block = server->m_env->getMap().getBlockNoCreateNoEx(p);
396
397                         bool surely_not_found_on_disk = false;
398                         bool block_is_invalid = false;
399                         if(block != NULL)
400                         {
401                                 // Reset usage timer, this block will be of use in the future.
402                                 block->resetUsageTimer();
403
404                                 // Block is dummy if data doesn't exist.
405                                 // It means it has been not found from disk and not generated
406                                 if(block->isDummy())
407                                 {
408                                         surely_not_found_on_disk = true;
409                                 }
410
411                                 // Block is valid if lighting is up-to-date and data exists
412                                 if(block->isValid() == false)
413                                 {
414                                         block_is_invalid = true;
415                                 }
416
417                                 /*if(block->isFullyGenerated() == false)
418                                 {
419                                         block_is_invalid = true;
420                                 }*/
421
422 #if 0
423                                 v2s16 p2d(p.X, p.Z);
424                                 ServerMap *map = (ServerMap*)(&server->m_env->getMap());
425                                 v2s16 chunkpos = map->sector_to_chunk(p2d);
426                                 if(map->chunkNonVolatile(chunkpos) == false)
427                                         block_is_invalid = true;
428 #endif
429                                 if(block->isGenerated() == false)
430                                         block_is_invalid = true;
431 #if 1
432                                 /*
433                                         If block is not close, don't send it unless it is near
434                                         ground level.
435
436                                         Block is near ground level if night-time mesh
437                                         differs from day-time mesh.
438                                 */
439                                 if(d >= 4)
440                                 {
441                                         if(block->getDayNightDiff() == false)
442                                                 continue;
443                                 }
444 #endif
445                         }
446
447                         /*
448                                 If block has been marked to not exist on disk (dummy)
449                                 and generating new ones is not wanted, skip block.
450                         */
451                         if(generate == false && surely_not_found_on_disk == true)
452                         {
453                                 // get next one.
454                                 continue;
455                         }
456
457                         /*
458                                 Add inexistent block to emerge queue.
459                         */
460                         if(block == NULL || surely_not_found_on_disk || block_is_invalid)
461                         {
462                         /*      //TODO: Get value from somewhere
463                                 // Allow only one block in emerge queue
464                                 //if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
465                                 // Allow two blocks in queue per client
466                                 //if(server->m_emerge_queue.peerItemCount(peer_id) < 2)
467                                 u32 max_emerge = 5;
468                                 // Make it more responsive when needing to generate stuff
469                                 if(surely_not_found_on_disk)
470                                         max_emerge = 1;
471                                 if(server->m_emerge_queue.peerItemCount(peer_id) < max_emerge)
472                                 {
473                                         //infostream<<"Adding block to emerge queue"<<std::endl;
474
475                                         // Add it to the emerge queue and trigger the thread
476
477                                         u8 flags = 0;
478                                         if(generate == false)
479                                                 flags |= BLOCK_EMERGE_FLAG_FROMDISK;
480
481                                         server->m_emerge_queue.addBlock(peer_id, p, flags);
482                                         server->m_emergethread.trigger();
483
484                                         if(nearest_emerged_d == -1)
485                                                 nearest_emerged_d = d;
486                                 } else {
487                                         if(nearest_emergefull_d == -1)
488                                                 nearest_emergefull_d = d;
489                                         goto queue_full_break;
490                                 }
491                         */
492
493                                 if (server->m_emerge->enqueueBlockEmerge(peer_id, p, generate)) {
494                                         if (nearest_emerged_d == -1)
495                                                 nearest_emerged_d = d;
496                                 } else {
497                                         if (nearest_emergefull_d == -1)
498                                                 nearest_emergefull_d = d;
499                                         goto queue_full_break;
500                                 }
501                                 
502                                 // get next one.
503                                 continue;
504                         }
505
506                         if(nearest_sent_d == -1)
507                                 nearest_sent_d = d;
508
509                         /*
510                                 Add block to send queue
511                         */
512
513                         /*errorstream<<"sending from d="<<d<<" to "
514                                         <<server->getPlayerName(peer_id)<<std::endl;*/
515
516                         PrioritySortedBlockTransfer q((float)d, p, peer_id);
517
518                         dest.push_back(q);
519
520                         num_blocks_selected += 1;
521                 }
522         }
523 queue_full_break:
524
525         //infostream<<"Stopped at "<<d<<std::endl;
526
527         // If nothing was found for sending and nothing was queued for
528         // emerging, continue next time browsing from here
529         if(nearest_emerged_d != -1){
530                 new_nearest_unsent_d = nearest_emerged_d;
531         } else if(nearest_emergefull_d != -1){
532                 new_nearest_unsent_d = nearest_emergefull_d;
533         } else {
534                 if(d > g_settings->getS16("max_block_send_distance")){
535                         new_nearest_unsent_d = 0;
536                         m_nothing_to_send_pause_timer = 2.0;
537                         /*infostream<<"GetNextBlocks(): d wrapped around for "
538                                         <<server->getPlayerName(peer_id)
539                                         <<"; setting to 0 and pausing"<<std::endl;*/
540                 } else {
541                         if(nearest_sent_d != -1)
542                                 new_nearest_unsent_d = nearest_sent_d;
543                         else
544                                 new_nearest_unsent_d = d;
545                 }
546         }
547
548         if(new_nearest_unsent_d != -1)
549                 m_nearest_unsent_d = new_nearest_unsent_d;
550
551         /*timer_result = timer.stop(true);
552         if(timer_result != 0)
553                 infostream<<"GetNextBlocks timeout: "<<timer_result<<" (!=0)"<<std::endl;*/
554 }
555
556 void RemoteClient::GotBlock(v3s16 p)
557 {
558         if(m_blocks_sending.find(p) != m_blocks_sending.end())
559                 m_blocks_sending.erase(p);
560         else
561         {
562                 /*infostream<<"RemoteClient::GotBlock(): Didn't find in"
563                                 " m_blocks_sending"<<std::endl;*/
564                 m_excess_gotblocks++;
565         }
566         m_blocks_sent.insert(p);
567 }
568
569 void RemoteClient::SentBlock(v3s16 p)
570 {
571         if(m_blocks_sending.find(p) == m_blocks_sending.end())
572                 m_blocks_sending[p] = 0.0;
573         else
574                 infostream<<"RemoteClient::SentBlock(): Sent block"
575                                 " already in m_blocks_sending"<<std::endl;
576 }
577
578 void RemoteClient::SetBlockNotSent(v3s16 p)
579 {
580         m_nearest_unsent_d = 0;
581
582         if(m_blocks_sending.find(p) != m_blocks_sending.end())
583                 m_blocks_sending.erase(p);
584         if(m_blocks_sent.find(p) != m_blocks_sent.end())
585                 m_blocks_sent.erase(p);
586 }
587
588 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
589 {
590         m_nearest_unsent_d = 0;
591
592         for(std::map<v3s16, MapBlock*>::iterator
593                         i = blocks.begin();
594                         i != blocks.end(); ++i)
595         {
596                 v3s16 p = i->first;
597
598                 if(m_blocks_sending.find(p) != m_blocks_sending.end())
599                         m_blocks_sending.erase(p);
600                 if(m_blocks_sent.find(p) != m_blocks_sent.end())
601                         m_blocks_sent.erase(p);
602         }
603 }
604
605 /*
606         PlayerInfo
607 */
608
609 PlayerInfo::PlayerInfo()
610 {
611         name[0] = 0;
612         avg_rtt = 0;
613 }
614
615 void PlayerInfo::PrintLine(std::ostream *s)
616 {
617         (*s)<<id<<": ";
618         (*s)<<"\""<<name<<"\" ("
619                         <<(position.X/10)<<","<<(position.Y/10)
620                         <<","<<(position.Z/10)<<") ";
621         address.print(s);
622         (*s)<<" avg_rtt="<<avg_rtt;
623         (*s)<<std::endl;
624 }
625
626 /*
627         Server
628 */
629
630 Server::Server(
631                 const std::string &path_world,
632                 const std::string &path_config,
633                 const SubgameSpec &gamespec,
634                 bool simple_singleplayer_mode
635         ):
636         m_path_world(path_world),
637         m_path_config(path_config),
638         m_gamespec(gamespec),
639         m_simple_singleplayer_mode(simple_singleplayer_mode),
640         m_async_fatal_error(""),
641         m_env(NULL),
642         m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT,
643               g_settings->getBool("enable_ipv6") && g_settings->getBool("ipv6_server"), 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_script(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
765         m_script = new ScriptApi(this);
766
767
768         // Load and run builtin.lua
769         infostream<<"Server: Loading builtin.lua [\""
770                         <<builtinpath<<"\"]"<<std::endl;
771         bool success = m_script->loadMod(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 = m_script->loadMod(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_script, this, this);
809         
810         m_emerge->initMapgens(servermap->getMapgenParams());
811
812         // Give environment reference to scripting api
813         m_script->initializeEnvironment(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                 m_script->on_shutdown();
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         delete m_script;
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 = m_script->getAuth(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                         m_script->createAuth(playername, initial_password);
1968                 }
1969
1970                 has_auth = m_script->getAuth(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                         /*
2406                                 Disable dropping items out of craftpreview
2407                         */
2408                         if(da->from_list == "craftpreview")
2409                         {
2410                                 infostream<<"Ignoring IDropAction from "
2411                                                 <<(da->from_inv.dump())<<":"<<da->from_list
2412                                                 <<" because src is "<<da->from_list<<std::endl;
2413                                 delete a;
2414                                 return;
2415                         }
2416
2417                         // Disallow dropping items if not allowed to interact
2418                         if(!checkPriv(player->getName(), "interact"))
2419                         {
2420                                 delete a;
2421                                 return;
2422                         }
2423                 }
2424                 /*
2425                         Handle restrictions and special cases of the craft action
2426                 */
2427                 else if(a->getType() == IACTION_CRAFT)
2428                 {
2429                         ICraftAction *ca = (ICraftAction*)a;
2430
2431                         ca->craft_inv.applyCurrentPlayer(player->getName());
2432
2433                         setInventoryModified(ca->craft_inv);
2434
2435                         //bool craft_inv_is_current_player =
2436                         //      (ca->craft_inv.type == InventoryLocation::PLAYER) &&
2437                         //      (ca->craft_inv.name == player->getName());
2438
2439                         // Disallow crafting if not allowed to interact
2440                         if(!checkPriv(player->getName(), "interact"))
2441                         {
2442                                 infostream<<"Cannot craft: "
2443                                                 <<"No interact privilege"<<std::endl;
2444                                 delete a;
2445                                 return;
2446                         }
2447                 }
2448
2449                 // Do the action
2450                 a->apply(this, playersao, this);
2451                 // Eat the action
2452                 delete a;
2453         }
2454         else if(command == TOSERVER_CHAT_MESSAGE)
2455         {
2456                 /*
2457                         u16 command
2458                         u16 length
2459                         wstring message
2460                 */
2461                 u8 buf[6];
2462                 std::string datastring((char*)&data[2], datasize-2);
2463                 std::istringstream is(datastring, std::ios_base::binary);
2464
2465                 // Read stuff
2466                 is.read((char*)buf, 2);
2467                 u16 len = readU16(buf);
2468
2469                 std::wstring message;
2470                 for(u16 i=0; i<len; i++)
2471                 {
2472                         is.read((char*)buf, 2);
2473                         message += (wchar_t)readU16(buf);
2474                 }
2475
2476                 // If something goes wrong, this player is to blame
2477                 RollbackScopeActor rollback_scope(m_rollback,
2478                                 std::string("player:")+player->getName());
2479
2480                 // Get player name of this client
2481                 std::wstring name = narrow_to_wide(player->getName());
2482
2483                 // Run script hook
2484                 bool ate = m_script->on_chat_message(player->getName(),
2485                                 wide_to_narrow(message));
2486                 // If script ate the message, don't proceed
2487                 if(ate)
2488                         return;
2489
2490                 // Line to send to players
2491                 std::wstring line;
2492                 // Whether to send to the player that sent the line
2493                 bool send_to_sender = false;
2494                 // Whether to send to other players
2495                 bool send_to_others = false;
2496
2497                 // Commands are implemented in Lua, so only catch invalid
2498                 // commands that were not "eaten" and send an error back
2499                 if(message[0] == L'/')
2500                 {
2501                         message = message.substr(1);
2502                         send_to_sender = true;
2503                         if(message.length() == 0)
2504                                 line += L"-!- Empty command";
2505                         else
2506                                 line += L"-!- Invalid command: " + str_split(message, L' ')[0];
2507                 }
2508                 else
2509                 {
2510                         if(checkPriv(player->getName(), "shout")){
2511                                 line += L"<";
2512                                 line += name;
2513                                 line += L"> ";
2514                                 line += message;
2515                                 send_to_others = true;
2516                         } else {
2517                                 line += L"-!- You don't have permission to shout.";
2518                                 send_to_sender = true;
2519                         }
2520                 }
2521
2522                 if(line != L"")
2523                 {
2524                         if(send_to_others)
2525                                 actionstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
2526
2527                         /*
2528                                 Send the message to clients
2529                         */
2530                         for(std::map<u16, RemoteClient*>::iterator
2531                                 i = m_clients.begin();
2532                                 i != m_clients.end(); ++i)
2533                         {
2534                                 // Get client and check that it is valid
2535                                 RemoteClient *client = i->second;
2536                                 assert(client->peer_id == i->first);
2537                                 if(client->serialization_version == SER_FMT_VER_INVALID)
2538                                         continue;
2539
2540                                 // Filter recipient
2541                                 bool sender_selected = (peer_id == client->peer_id);
2542                                 if(sender_selected == true && send_to_sender == false)
2543                                         continue;
2544                                 if(sender_selected == false && send_to_others == false)
2545                                         continue;
2546
2547                                 SendChatMessage(client->peer_id, line);
2548                         }
2549                 }
2550         }
2551         else if(command == TOSERVER_DAMAGE)
2552         {
2553                 std::string datastring((char*)&data[2], datasize-2);
2554                 std::istringstream is(datastring, std::ios_base::binary);
2555                 u8 damage = readU8(is);
2556
2557                 if(g_settings->getBool("enable_damage"))
2558                 {
2559                         actionstream<<player->getName()<<" damaged by "
2560                                         <<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
2561                                         <<std::endl;
2562
2563                         playersao->setHP(playersao->getHP() - damage);
2564
2565                         if(playersao->getHP() == 0 && playersao->m_hp_not_sent)
2566                                 DiePlayer(peer_id);
2567
2568                         if(playersao->m_hp_not_sent)
2569                                 SendPlayerHP(peer_id);
2570                 }
2571         }
2572         else if(command == TOSERVER_PASSWORD)
2573         {
2574                 /*
2575                         [0] u16 TOSERVER_PASSWORD
2576                         [2] u8[28] old password
2577                         [30] u8[28] new password
2578                 */
2579
2580                 if(datasize != 2+PASSWORD_SIZE*2)
2581                         return;
2582                 /*char password[PASSWORD_SIZE];
2583                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2584                         password[i] = data[2+i];
2585                 password[PASSWORD_SIZE-1] = 0;*/
2586                 std::string oldpwd;
2587                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2588                 {
2589                         char c = data[2+i];
2590                         if(c == 0)
2591                                 break;
2592                         oldpwd += c;
2593                 }
2594                 std::string newpwd;
2595                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2596                 {
2597                         char c = data[2+PASSWORD_SIZE+i];
2598                         if(c == 0)
2599                                 break;
2600                         newpwd += c;
2601                 }
2602
2603                 if(!base64_is_valid(newpwd)){
2604                         infostream<<"Server: "<<player->getName()<<" supplied invalid password hash"<<std::endl;
2605                         // Wrong old password supplied!!
2606                         SendChatMessage(peer_id, L"Invalid new password hash supplied. Password NOT changed.");
2607                         return;
2608                 }
2609
2610                 infostream<<"Server: Client requests a password change from "
2611                                 <<"'"<<oldpwd<<"' to '"<<newpwd<<"'"<<std::endl;
2612
2613                 std::string playername = player->getName();
2614
2615                 std::string checkpwd;
2616                 m_script->getAuth(playername, &checkpwd, NULL);
2617
2618                 if(oldpwd != checkpwd)
2619                 {
2620                         infostream<<"Server: invalid old password"<<std::endl;
2621                         // Wrong old password supplied!!
2622                         SendChatMessage(peer_id, L"Invalid old password supplied. Password NOT changed.");
2623                         return;
2624                 }
2625
2626                 bool success = m_script->setPassword(playername, newpwd);
2627                 if(success){
2628                         actionstream<<player->getName()<<" changes password"<<std::endl;
2629                         SendChatMessage(peer_id, L"Password change successful.");
2630                 } else {
2631                         actionstream<<player->getName()<<" tries to change password but "
2632                                         <<"it fails"<<std::endl;
2633                         SendChatMessage(peer_id, L"Password change failed or inavailable.");
2634                 }
2635         }
2636         else if(command == TOSERVER_PLAYERITEM)
2637         {
2638                 if (datasize < 2+2)
2639                         return;
2640
2641                 u16 item = readU16(&data[2]);
2642                 playersao->setWieldIndex(item);
2643         }
2644         else if(command == TOSERVER_RESPAWN)
2645         {
2646                 if(player->hp != 0 || !g_settings->getBool("enable_damage"))
2647                         return;
2648
2649                 RespawnPlayer(peer_id);
2650
2651                 actionstream<<player->getName()<<" respawns at "
2652                                 <<PP(player->getPosition()/BS)<<std::endl;
2653
2654                 // ActiveObject is added to environment in AsyncRunStep after
2655                 // the previous addition has been succesfully removed
2656         }
2657         else if(command == TOSERVER_REQUEST_MEDIA) {
2658                 std::string datastring((char*)&data[2], datasize-2);
2659                 std::istringstream is(datastring, std::ios_base::binary);
2660
2661                 std::list<MediaRequest> tosend;
2662                 u16 numfiles = readU16(is);
2663
2664                 infostream<<"Sending "<<numfiles<<" files to "
2665                                 <<getPlayerName(peer_id)<<std::endl;
2666                 verbosestream<<"TOSERVER_REQUEST_MEDIA: "<<std::endl;
2667
2668                 for(int i = 0; i < numfiles; i++) {
2669                         std::string name = deSerializeString(is);
2670                         tosend.push_back(MediaRequest(name));
2671                         verbosestream<<"TOSERVER_REQUEST_MEDIA: requested file "
2672                                         <<name<<std::endl;
2673                 }
2674
2675                 sendRequestedMedia(peer_id, tosend);
2676
2677                 // Now the client should know about everything
2678                 // (definitions and files)
2679                 getClient(peer_id)->definitions_sent = true;
2680         }
2681         else if(command == TOSERVER_RECEIVED_MEDIA) {
2682                 getClient(peer_id)->definitions_sent = true;
2683         }
2684         else if(command == TOSERVER_INTERACT)
2685         {
2686                 std::string datastring((char*)&data[2], datasize-2);
2687                 std::istringstream is(datastring, std::ios_base::binary);
2688
2689                 /*
2690                         [0] u16 command
2691                         [2] u8 action
2692                         [3] u16 item
2693                         [5] u32 length of the next item
2694                         [9] serialized PointedThing
2695                         actions:
2696                         0: start digging (from undersurface) or use
2697                         1: stop digging (all parameters ignored)
2698                         2: digging completed
2699                         3: place block or item (to abovesurface)
2700                         4: use item
2701                 */
2702                 u8 action = readU8(is);
2703                 u16 item_i = readU16(is);
2704                 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
2705                 PointedThing pointed;
2706                 pointed.deSerialize(tmp_is);
2707
2708                 verbosestream<<"TOSERVER_INTERACT: action="<<(int)action<<", item="
2709                                 <<item_i<<", pointed="<<pointed.dump()<<std::endl;
2710
2711                 if(player->hp == 0)
2712                 {
2713                         verbosestream<<"TOSERVER_INTERACT: "<<player->getName()
2714                                 <<" tried to interact, but is dead!"<<std::endl;
2715                         return;
2716                 }
2717
2718                 v3f player_pos = playersao->getLastGoodPosition();
2719
2720                 // Update wielded item
2721                 playersao->setWieldIndex(item_i);
2722
2723                 // Get pointed to node (undefined if not POINTEDTYPE_NODE)
2724                 v3s16 p_under = pointed.node_undersurface;
2725                 v3s16 p_above = pointed.node_abovesurface;
2726
2727                 // Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
2728                 ServerActiveObject *pointed_object = NULL;
2729                 if(pointed.type == POINTEDTHING_OBJECT)
2730                 {
2731                         pointed_object = m_env->getActiveObject(pointed.object_id);
2732                         if(pointed_object == NULL)
2733                         {
2734                                 verbosestream<<"TOSERVER_INTERACT: "
2735                                         "pointed object is NULL"<<std::endl;
2736                                 return;
2737                         }
2738
2739                 }
2740
2741                 v3f pointed_pos_under = player_pos;
2742                 v3f pointed_pos_above = player_pos;
2743                 if(pointed.type == POINTEDTHING_NODE)
2744                 {
2745                         pointed_pos_under = intToFloat(p_under, BS);
2746                         pointed_pos_above = intToFloat(p_above, BS);
2747                 }
2748                 else if(pointed.type == POINTEDTHING_OBJECT)
2749                 {
2750                         pointed_pos_under = pointed_object->getBasePosition();
2751                         pointed_pos_above = pointed_pos_under;
2752                 }
2753
2754                 /*
2755                         Check that target is reasonably close
2756                         (only when digging or placing things)
2757                 */
2758                 if(action == 0 || action == 2 || action == 3)
2759                 {
2760                         float d = player_pos.getDistanceFrom(pointed_pos_under);
2761                         float max_d = BS * 14; // Just some large enough value
2762                         if(d > max_d){
2763                                 actionstream<<"Player "<<player->getName()
2764                                                 <<" tried to access "<<pointed.dump()
2765                                                 <<" from too far: "
2766                                                 <<"d="<<d<<", max_d="<<max_d
2767                                                 <<". ignoring."<<std::endl;
2768                                 // Re-send block to revert change on client-side
2769                                 RemoteClient *client = getClient(peer_id);
2770                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2771                                 client->SetBlockNotSent(blockpos);
2772                                 // Do nothing else
2773                                 return;
2774                         }
2775                 }
2776
2777                 /*
2778                         Make sure the player is allowed to do it
2779                 */
2780                 if(!checkPriv(player->getName(), "interact"))
2781                 {
2782                         actionstream<<player->getName()<<" attempted to interact with "
2783                                         <<pointed.dump()<<" without 'interact' privilege"
2784                                         <<std::endl;
2785                         // Re-send block to revert change on client-side
2786                         RemoteClient *client = getClient(peer_id);
2787                         // Digging completed -> under
2788                         if(action == 2){
2789                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2790                                 client->SetBlockNotSent(blockpos);
2791                         }
2792                         // Placement -> above
2793                         if(action == 3){
2794                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
2795                                 client->SetBlockNotSent(blockpos);
2796                         }
2797                         return;
2798                 }
2799
2800                 /*
2801                         If something goes wrong, this player is to blame
2802                 */
2803                 RollbackScopeActor rollback_scope(m_rollback,
2804                                 std::string("player:")+player->getName());
2805
2806                 /*
2807                         0: start digging or punch object
2808                 */
2809                 if(action == 0)
2810                 {
2811                         if(pointed.type == POINTEDTHING_NODE)
2812                         {
2813                                 /*
2814                                         NOTE: This can be used in the future to check if
2815                                         somebody is cheating, by checking the timing.
2816                                 */
2817                                 MapNode n(CONTENT_IGNORE);
2818                                 try
2819                                 {
2820                                         n = m_env->getMap().getNode(p_under);
2821                                 }
2822                                 catch(InvalidPositionException &e)
2823                                 {
2824                                         infostream<<"Server: Not punching: Node not found."
2825                                                         <<" Adding block to emerge queue."
2826                                                         <<std::endl;
2827                                         m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2828                                 }
2829                                 if(n.getContent() != CONTENT_IGNORE)
2830                                         m_script->node_on_punch(p_under, n, playersao);
2831                                 // Cheat prevention
2832                                 playersao->noCheatDigStart(p_under);
2833                         }
2834                         else if(pointed.type == POINTEDTHING_OBJECT)
2835                         {
2836                                 // Skip if object has been removed
2837                                 if(pointed_object->m_removed)
2838                                         return;
2839
2840                                 actionstream<<player->getName()<<" punches object "
2841                                                 <<pointed.object_id<<": "
2842                                                 <<pointed_object->getDescription()<<std::endl;
2843
2844                                 ItemStack punchitem = playersao->getWieldedItem();
2845                                 ToolCapabilities toolcap =
2846                                                 punchitem.getToolCapabilities(m_itemdef);
2847                                 v3f dir = (pointed_object->getBasePosition() -
2848                                                 (player->getPosition() + player->getEyeOffset())
2849                                                         ).normalize();
2850                                 float time_from_last_punch =
2851                                         playersao->resetTimeFromLastPunch();
2852                                 pointed_object->punch(dir, &toolcap, playersao,
2853                                                 time_from_last_punch);
2854                         }
2855
2856                 } // action == 0
2857
2858                 /*
2859                         1: stop digging
2860                 */
2861                 else if(action == 1)
2862                 {
2863                 } // action == 1
2864
2865                 /*
2866                         2: Digging completed
2867                 */
2868                 else if(action == 2)
2869                 {
2870                         // Only digging of nodes
2871                         if(pointed.type == POINTEDTHING_NODE)
2872                         {
2873                                 MapNode n(CONTENT_IGNORE);
2874                                 try
2875                                 {
2876                                         n = m_env->getMap().getNode(p_under);
2877                                 }
2878                                 catch(InvalidPositionException &e)
2879                                 {
2880                                         infostream<<"Server: Not finishing digging: Node not found."
2881                                                         <<" Adding block to emerge queue."
2882                                                         <<std::endl;
2883                                         m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2884                                 }
2885
2886                                 /* Cheat prevention */
2887                                 bool is_valid_dig = true;
2888                                 if(!isSingleplayer() && !g_settings->getBool("disable_anticheat"))
2889                                 {
2890                                         v3s16 nocheat_p = playersao->getNoCheatDigPos();
2891                                         float nocheat_t = playersao->getNoCheatDigTime();
2892                                         playersao->noCheatDigEnd();
2893                                         // If player didn't start digging this, ignore dig
2894                                         if(nocheat_p != p_under){
2895                                                 infostream<<"Server: NoCheat: "<<player->getName()
2896                                                                 <<" started digging "
2897                                                                 <<PP(nocheat_p)<<" and completed digging "
2898                                                                 <<PP(p_under)<<"; not digging."<<std::endl;
2899                                                 is_valid_dig = false;
2900                                         }
2901                                         // Get player's wielded item
2902                                         ItemStack playeritem;
2903                                         InventoryList *mlist = playersao->getInventory()->getList("main");
2904                                         if(mlist != NULL)
2905                                                 playeritem = mlist->getItem(playersao->getWieldIndex());
2906                                         ToolCapabilities playeritem_toolcap =
2907                                                         playeritem.getToolCapabilities(m_itemdef);
2908                                         // Get diggability and expected digging time
2909                                         DigParams params = getDigParams(m_nodedef->get(n).groups,
2910                                                         &playeritem_toolcap);
2911                                         // If can't dig, try hand
2912                                         if(!params.diggable){
2913                                                 const ItemDefinition &hand = m_itemdef->get("");
2914                                                 const ToolCapabilities *tp = hand.tool_capabilities;
2915                                                 if(tp)
2916                                                         params = getDigParams(m_nodedef->get(n).groups, tp);
2917                                         }
2918                                         // If can't dig, ignore dig
2919                                         if(!params.diggable){
2920                                                 infostream<<"Server: NoCheat: "<<player->getName()
2921                                                                 <<" completed digging "<<PP(p_under)
2922                                                                 <<", which is not diggable with tool. not digging."
2923                                                                 <<std::endl;
2924                                                 is_valid_dig = false;
2925                                         }
2926                                         // If time is considerably too short, ignore dig
2927                                         // Check time only for medium and slow timed digs
2928                                         if(params.diggable && params.time > 0.3 && nocheat_t < 0.5 * params.time){
2929                                                 infostream<<"Server: NoCheat: "<<player->getName()
2930                                                                 <<" completed digging "
2931                                                                 <<PP(p_under)<<" in "<<nocheat_t<<"s; expected "
2932                                                                 <<params.time<<"s; not digging."<<std::endl;
2933                                                 is_valid_dig = false;
2934                                         }
2935                                 }
2936
2937                                 /* Actually dig node */
2938
2939                                 if(is_valid_dig && n.getContent() != CONTENT_IGNORE)
2940                                         m_script->node_on_dig(p_under, n, playersao);
2941
2942                                 // Send unusual result (that is, node not being removed)
2943                                 if(m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR)
2944                                 {
2945                                         // Re-send block to revert change on client-side
2946                                         RemoteClient *client = getClient(peer_id);
2947                                         v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2948                                         client->SetBlockNotSent(blockpos);
2949                                 }
2950                         }
2951                 } // action == 2
2952
2953                 /*
2954                         3: place block or right-click object
2955                 */
2956                 else if(action == 3)
2957                 {
2958                         ItemStack item = playersao->getWieldedItem();
2959
2960                         // Reset build time counter
2961                         if(pointed.type == POINTEDTHING_NODE &&
2962                                         item.getDefinition(m_itemdef).type == ITEM_NODE)
2963                                 getClient(peer_id)->m_time_from_building = 0.0;
2964
2965                         if(pointed.type == POINTEDTHING_OBJECT)
2966                         {
2967                                 // Right click object
2968
2969                                 // Skip if object has been removed
2970                                 if(pointed_object->m_removed)
2971                                         return;
2972
2973                                 actionstream<<player->getName()<<" right-clicks object "
2974                                                 <<pointed.object_id<<": "
2975                                                 <<pointed_object->getDescription()<<std::endl;
2976
2977                                 // Do stuff
2978                                 pointed_object->rightClick(playersao);
2979                         }
2980                         else if(m_script->item_OnPlace(
2981                                         item, playersao, pointed))
2982                         {
2983                                 // Placement was handled in lua
2984
2985                                 // Apply returned ItemStack
2986                                 playersao->setWieldedItem(item);
2987                         }
2988
2989                         // If item has node placement prediction, always send the
2990                         // blocks to make sure the client knows what exactly happened
2991                         if(item.getDefinition(m_itemdef).node_placement_prediction != ""){
2992                                 RemoteClient *client = getClient(peer_id);
2993                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
2994                                 client->SetBlockNotSent(blockpos);
2995                                 v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2996                                 if(blockpos2 != blockpos){
2997                                         client->SetBlockNotSent(blockpos2);
2998                                 }
2999                         }
3000                 } // action == 3
3001
3002                 /*
3003                         4: use
3004                 */
3005                 else if(action == 4)
3006                 {
3007                         ItemStack item = playersao->getWieldedItem();
3008
3009                         actionstream<<player->getName()<<" uses "<<item.name
3010                                         <<", pointing at "<<pointed.dump()<<std::endl;
3011
3012                         if(m_script->item_OnUse(
3013                                         item, playersao, pointed))
3014                         {
3015                                 // Apply returned ItemStack
3016                                 playersao->setWieldedItem(item);
3017                         }
3018
3019                 } // action == 4
3020                 
3021
3022                 /*
3023                         Catch invalid actions
3024                 */
3025                 else
3026                 {
3027                         infostream<<"WARNING: Server: Invalid action "
3028                                         <<action<<std::endl;
3029                 }
3030         }
3031         else if(command == TOSERVER_REMOVED_SOUNDS)
3032         {
3033                 std::string datastring((char*)&data[2], datasize-2);
3034                 std::istringstream is(datastring, std::ios_base::binary);
3035
3036                 int num = readU16(is);
3037                 for(int k=0; k<num; k++){
3038                         s32 id = readS32(is);
3039                         std::map<s32, ServerPlayingSound>::iterator i =
3040                                         m_playing_sounds.find(id);
3041                         if(i == m_playing_sounds.end())
3042                                 continue;
3043                         ServerPlayingSound &psound = i->second;
3044                         psound.clients.erase(peer_id);
3045                         if(psound.clients.size() == 0)
3046                                 m_playing_sounds.erase(i++);
3047                 }
3048         }
3049         else if(command == TOSERVER_NODEMETA_FIELDS)
3050         {
3051                 std::string datastring((char*)&data[2], datasize-2);
3052                 std::istringstream is(datastring, std::ios_base::binary);
3053
3054                 v3s16 p = readV3S16(is);
3055                 std::string formname = deSerializeString(is);
3056                 int num = readU16(is);
3057                 std::map<std::string, std::string> fields;
3058                 for(int k=0; k<num; k++){
3059                         std::string fieldname = deSerializeString(is);
3060                         std::string fieldvalue = deSerializeLongString(is);
3061                         fields[fieldname] = fieldvalue;
3062                 }
3063
3064                 // If something goes wrong, this player is to blame
3065                 RollbackScopeActor rollback_scope(m_rollback,
3066                                 std::string("player:")+player->getName());
3067
3068                 // Check the target node for rollback data; leave others unnoticed
3069                 RollbackNode rn_old(&m_env->getMap(), p, this);
3070
3071                 m_script->node_on_receive_fields(p, formname, fields,playersao);
3072
3073                 // Report rollback data
3074                 RollbackNode rn_new(&m_env->getMap(), p, this);
3075                 if(rollback() && rn_new != rn_old){
3076                         RollbackAction action;
3077                         action.setSetNode(p, rn_old, rn_new);
3078                         rollback()->reportAction(action);
3079                 }
3080         }
3081         else if(command == TOSERVER_INVENTORY_FIELDS)
3082         {
3083                 std::string datastring((char*)&data[2], datasize-2);
3084                 std::istringstream is(datastring, std::ios_base::binary);
3085
3086                 std::string formname = deSerializeString(is);
3087                 int num = readU16(is);
3088                 std::map<std::string, std::string> fields;
3089                 for(int k=0; k<num; k++){
3090                         std::string fieldname = deSerializeString(is);
3091                         std::string fieldvalue = deSerializeLongString(is);
3092                         fields[fieldname] = fieldvalue;
3093                 }
3094
3095                 m_script->on_playerReceiveFields(playersao, formname, fields);
3096         }
3097         else
3098         {
3099                 infostream<<"Server::ProcessData(): Ignoring "
3100                                 "unknown command "<<command<<std::endl;
3101         }
3102
3103         } //try
3104         catch(SendFailedException &e)
3105         {
3106                 errorstream<<"Server::ProcessData(): SendFailedException: "
3107                                 <<"what="<<e.what()
3108                                 <<std::endl;
3109         }
3110 }
3111
3112 void Server::onMapEditEvent(MapEditEvent *event)
3113 {
3114         //infostream<<"Server::onMapEditEvent()"<<std::endl;
3115         if(m_ignore_map_edit_events)
3116                 return;
3117         if(m_ignore_map_edit_events_area.contains(event->getArea()))
3118                 return;
3119         MapEditEvent *e = event->clone();
3120         m_unsent_map_edit_queue.push_back(e);
3121 }
3122
3123 Inventory* Server::getInventory(const InventoryLocation &loc)
3124 {
3125         switch(loc.type){
3126         case InventoryLocation::UNDEFINED:
3127         {}
3128         break;
3129         case InventoryLocation::CURRENT_PLAYER:
3130         {}
3131         break;
3132         case InventoryLocation::PLAYER:
3133         {
3134                 Player *player = m_env->getPlayer(loc.name.c_str());
3135                 if(!player)
3136                         return NULL;
3137                 PlayerSAO *playersao = player->getPlayerSAO();
3138                 if(!playersao)
3139                         return NULL;
3140                 return playersao->getInventory();
3141         }
3142         break;
3143         case InventoryLocation::NODEMETA:
3144         {
3145                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3146                 if(!meta)
3147                         return NULL;
3148                 return meta->getInventory();
3149         }
3150         break;
3151         case InventoryLocation::DETACHED:
3152         {
3153                 if(m_detached_inventories.count(loc.name) == 0)
3154                         return NULL;
3155                 return m_detached_inventories[loc.name];
3156         }
3157         break;
3158         default:
3159                 assert(0);
3160         }
3161         return NULL;
3162 }
3163 void Server::setInventoryModified(const InventoryLocation &loc)
3164 {
3165         switch(loc.type){
3166         case InventoryLocation::UNDEFINED:
3167         {}
3168         break;
3169         case InventoryLocation::PLAYER:
3170         {
3171                 Player *player = m_env->getPlayer(loc.name.c_str());
3172                 if(!player)
3173                         return;
3174                 PlayerSAO *playersao = player->getPlayerSAO();
3175                 if(!playersao)
3176                         return;
3177                 playersao->m_inventory_not_sent = true;
3178                 playersao->m_wielded_item_not_sent = true;
3179         }
3180         break;
3181         case InventoryLocation::NODEMETA:
3182         {
3183                 v3s16 blockpos = getNodeBlockPos(loc.p);
3184
3185                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
3186                 if(block)
3187                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
3188
3189                 setBlockNotSent(blockpos);
3190         }
3191         break;
3192         case InventoryLocation::DETACHED:
3193         {
3194                 sendDetachedInventoryToAll(loc.name);
3195         }
3196         break;
3197         default:
3198                 assert(0);
3199         }
3200 }
3201
3202 //std::list<PlayerInfo> Server::getPlayerInfo()
3203 //{
3204 //      DSTACK(__FUNCTION_NAME);
3205 //      JMutexAutoLock envlock(m_env_mutex);
3206 //      JMutexAutoLock conlock(m_con_mutex);
3207 //
3208 //      std::list<PlayerInfo> list;
3209 //
3210 //      std::list<Player*> players = m_env->getPlayers();
3211 //
3212 //      std::list<Player*>::iterator i;
3213 //      for(i = players.begin();
3214 //                      i != players.end(); ++i)
3215 //      {
3216 //              PlayerInfo info;
3217 //
3218 //              Player *player = *i;
3219 //
3220 //              try{
3221 //                      // Copy info from connection to info struct
3222 //                      info.id = player->peer_id;
3223 //                      info.address = m_con.GetPeerAddress(player->peer_id);
3224 //                      info.avg_rtt = m_con.GetPeerAvgRTT(player->peer_id);
3225 //              }
3226 //              catch(con::PeerNotFoundException &e)
3227 //              {
3228 //                      // Set dummy peer info
3229 //                      info.id = 0;
3230 //                      info.address = Address(0,0,0,0,0);
3231 //                      info.avg_rtt = 0.0;
3232 //              }
3233 //
3234 //              snprintf(info.name, PLAYERNAME_SIZE, "%s", player->getName());
3235 //              info.position = player->getPosition();
3236 //
3237 //              list.push_back(info);
3238 //      }
3239 //
3240 //      return list;
3241 //}
3242
3243
3244 void Server::peerAdded(con::Peer *peer)
3245 {
3246         DSTACK(__FUNCTION_NAME);
3247         verbosestream<<"Server::peerAdded(): peer->id="
3248                         <<peer->id<<std::endl;
3249
3250         PeerChange c;
3251         c.type = PEER_ADDED;
3252         c.peer_id = peer->id;
3253         c.timeout = false;
3254         m_peer_change_queue.push_back(c);
3255 }
3256
3257 void Server::deletingPeer(con::Peer *peer, bool timeout)
3258 {
3259         DSTACK(__FUNCTION_NAME);
3260         verbosestream<<"Server::deletingPeer(): peer->id="
3261                         <<peer->id<<", timeout="<<timeout<<std::endl;
3262
3263         PeerChange c;
3264         c.type = PEER_REMOVED;
3265         c.peer_id = peer->id;
3266         c.timeout = timeout;
3267         m_peer_change_queue.push_back(c);
3268 }
3269
3270 /*
3271         Static send methods
3272 */
3273
3274 void Server::SendMovement(con::Connection &con, u16 peer_id)
3275 {
3276         DSTACK(__FUNCTION_NAME);
3277         std::ostringstream os(std::ios_base::binary);
3278
3279         writeU16(os, TOCLIENT_MOVEMENT);
3280         writeF1000(os, g_settings->getFloat("movement_acceleration_default"));
3281         writeF1000(os, g_settings->getFloat("movement_acceleration_air"));
3282         writeF1000(os, g_settings->getFloat("movement_acceleration_fast"));
3283         writeF1000(os, g_settings->getFloat("movement_speed_walk"));
3284         writeF1000(os, g_settings->getFloat("movement_speed_crouch"));
3285         writeF1000(os, g_settings->getFloat("movement_speed_fast"));
3286         writeF1000(os, g_settings->getFloat("movement_speed_climb"));
3287         writeF1000(os, g_settings->getFloat("movement_speed_jump"));
3288         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity"));
3289         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity_smooth"));
3290         writeF1000(os, g_settings->getFloat("movement_liquid_sink"));
3291         writeF1000(os, g_settings->getFloat("movement_gravity"));
3292
3293         // Make data buffer
3294         std::string s = os.str();
3295         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3296         // Send as reliable
3297         con.Send(peer_id, 0, data, true);
3298 }
3299
3300 void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp)
3301 {
3302         DSTACK(__FUNCTION_NAME);
3303         std::ostringstream os(std::ios_base::binary);
3304
3305         writeU16(os, TOCLIENT_HP);
3306         writeU8(os, hp);
3307
3308         // Make data buffer
3309         std::string s = os.str();
3310         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3311         // Send as reliable
3312         con.Send(peer_id, 0, data, true);
3313 }
3314
3315 void Server::SendAccessDenied(con::Connection &con, u16 peer_id,
3316                 const std::wstring &reason)
3317 {
3318         DSTACK(__FUNCTION_NAME);
3319         std::ostringstream os(std::ios_base::binary);
3320
3321         writeU16(os, TOCLIENT_ACCESS_DENIED);
3322         os<<serializeWideString(reason);
3323
3324         // Make data buffer
3325         std::string s = os.str();
3326         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3327         // Send as reliable
3328         con.Send(peer_id, 0, data, true);
3329 }
3330
3331 void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
3332                 bool set_camera_point_target, v3f camera_point_target)
3333 {
3334         DSTACK(__FUNCTION_NAME);
3335         std::ostringstream os(std::ios_base::binary);
3336
3337         writeU16(os, TOCLIENT_DEATHSCREEN);
3338         writeU8(os, set_camera_point_target);
3339         writeV3F1000(os, camera_point_target);
3340
3341         // Make data buffer
3342         std::string s = os.str();
3343         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3344         // Send as reliable
3345         con.Send(peer_id, 0, data, true);
3346 }
3347
3348 void Server::SendItemDef(con::Connection &con, u16 peer_id,
3349                 IItemDefManager *itemdef, u16 protocol_version)
3350 {
3351         DSTACK(__FUNCTION_NAME);
3352         std::ostringstream os(std::ios_base::binary);
3353
3354         /*
3355                 u16 command
3356                 u32 length of the next item
3357                 zlib-compressed serialized ItemDefManager
3358         */
3359         writeU16(os, TOCLIENT_ITEMDEF);
3360         std::ostringstream tmp_os(std::ios::binary);
3361         itemdef->serialize(tmp_os, protocol_version);
3362         std::ostringstream tmp_os2(std::ios::binary);
3363         compressZlib(tmp_os.str(), tmp_os2);
3364         os<<serializeLongString(tmp_os2.str());
3365
3366         // Make data buffer
3367         std::string s = os.str();
3368         verbosestream<<"Server: Sending item definitions to id("<<peer_id
3369                         <<"): size="<<s.size()<<std::endl;
3370         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3371         // Send as reliable
3372         con.Send(peer_id, 0, data, true);
3373 }
3374
3375 void Server::SendNodeDef(con::Connection &con, u16 peer_id,
3376                 INodeDefManager *nodedef, u16 protocol_version)
3377 {
3378         DSTACK(__FUNCTION_NAME);
3379         std::ostringstream os(std::ios_base::binary);
3380
3381         /*
3382                 u16 command
3383                 u32 length of the next item
3384                 zlib-compressed serialized NodeDefManager
3385         */
3386         writeU16(os, TOCLIENT_NODEDEF);
3387         std::ostringstream tmp_os(std::ios::binary);
3388         nodedef->serialize(tmp_os, protocol_version);
3389         std::ostringstream tmp_os2(std::ios::binary);
3390         compressZlib(tmp_os.str(), tmp_os2);
3391         os<<serializeLongString(tmp_os2.str());
3392
3393         // Make data buffer
3394         std::string s = os.str();
3395         verbosestream<<"Server: Sending node definitions to id("<<peer_id
3396                         <<"): size="<<s.size()<<std::endl;
3397         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3398         // Send as reliable
3399         con.Send(peer_id, 0, data, true);
3400 }
3401
3402 /*
3403         Non-static send methods
3404 */
3405
3406 void Server::SendInventory(u16 peer_id)
3407 {
3408         DSTACK(__FUNCTION_NAME);
3409
3410         PlayerSAO *playersao = getPlayerSAO(peer_id);
3411         assert(playersao);
3412
3413         playersao->m_inventory_not_sent = false;
3414
3415         /*
3416                 Serialize it
3417         */
3418
3419         std::ostringstream os;
3420         playersao->getInventory()->serialize(os);
3421
3422         std::string s = os.str();
3423
3424         SharedBuffer<u8> data(s.size()+2);
3425         writeU16(&data[0], TOCLIENT_INVENTORY);
3426         memcpy(&data[2], s.c_str(), s.size());
3427
3428         // Send as reliable
3429         m_con.Send(peer_id, 0, data, true);
3430 }
3431
3432 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
3433 {
3434         DSTACK(__FUNCTION_NAME);
3435
3436         std::ostringstream os(std::ios_base::binary);
3437         u8 buf[12];
3438
3439         // Write command
3440         writeU16(buf, TOCLIENT_CHAT_MESSAGE);
3441         os.write((char*)buf, 2);
3442
3443         // Write length
3444         writeU16(buf, message.size());
3445         os.write((char*)buf, 2);
3446
3447         // Write string
3448         for(u32 i=0; i<message.size(); i++)
3449         {
3450                 u16 w = message[i];
3451                 writeU16(buf, w);
3452                 os.write((char*)buf, 2);
3453         }
3454
3455         // Make data buffer
3456         std::string s = os.str();
3457         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3458         // Send as reliable
3459         m_con.Send(peer_id, 0, data, true);
3460 }
3461
3462 void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec,
3463                                         const std::string formname)
3464 {
3465         DSTACK(__FUNCTION_NAME);
3466
3467         std::ostringstream os(std::ios_base::binary);
3468         u8 buf[12];
3469
3470         // Write command
3471         writeU16(buf, TOCLIENT_SHOW_FORMSPEC);
3472         os.write((char*)buf, 2);
3473         os<<serializeLongString(formspec);
3474         os<<serializeString(formname);
3475
3476         // Make data buffer
3477         std::string s = os.str();
3478         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3479         // Send as reliable
3480         m_con.Send(peer_id, 0, data, true);
3481 }
3482
3483 // Spawns a particle on peer with peer_id
3484 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
3485                                 float expirationtime, float size, bool collisiondetection,
3486                                 std::string texture)
3487 {
3488         DSTACK(__FUNCTION_NAME);
3489
3490         std::ostringstream os(std::ios_base::binary);
3491         writeU16(os, TOCLIENT_SPAWN_PARTICLE);
3492         writeV3F1000(os, pos);
3493         writeV3F1000(os, velocity);
3494         writeV3F1000(os, acceleration);
3495         writeF1000(os, expirationtime);
3496         writeF1000(os, size);
3497         writeU8(os,  collisiondetection);
3498         os<<serializeLongString(texture);
3499
3500         // Make data buffer
3501         std::string s = os.str();
3502         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3503         // Send as reliable
3504         m_con.Send(peer_id, 0, data, true);
3505 }
3506
3507 // Spawns a particle on all peers
3508 void Server::SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
3509                                 float expirationtime, float size, bool collisiondetection,
3510                                 std::string texture)
3511 {
3512         for(std::map<u16, RemoteClient*>::iterator
3513                 i = m_clients.begin();
3514                 i != m_clients.end(); i++)
3515         {
3516                 // Get client and check that it is valid
3517                 RemoteClient *client = i->second;
3518                 assert(client->peer_id == i->first);
3519                 if(client->serialization_version == SER_FMT_VER_INVALID)
3520                         continue;
3521
3522                 SendSpawnParticle(client->peer_id, pos, velocity, acceleration,
3523                         expirationtime, size, collisiondetection, texture);
3524         }
3525 }
3526
3527 // Adds a ParticleSpawner on peer with peer_id
3528 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
3529         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3530         float minsize, float maxsize, bool collisiondetection, std::string texture, u32 id)
3531 {
3532         DSTACK(__FUNCTION_NAME);
3533
3534         std::ostringstream os(std::ios_base::binary);
3535         writeU16(os, TOCLIENT_ADD_PARTICLESPAWNER);
3536
3537         writeU16(os, amount);
3538         writeF1000(os, spawntime);
3539         writeV3F1000(os, minpos);
3540         writeV3F1000(os, maxpos);
3541         writeV3F1000(os, minvel);
3542         writeV3F1000(os, maxvel);
3543         writeV3F1000(os, minacc);
3544         writeV3F1000(os, maxacc);
3545         writeF1000(os, minexptime);
3546         writeF1000(os, maxexptime);
3547         writeF1000(os, minsize);
3548         writeF1000(os, maxsize);
3549         writeU8(os,  collisiondetection);
3550         os<<serializeLongString(texture);
3551         writeU32(os, id);
3552
3553         // Make data buffer
3554         std::string s = os.str();
3555         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3556         // Send as reliable
3557         m_con.Send(peer_id, 0, data, true);
3558 }
3559
3560 // Adds a ParticleSpawner on all peers
3561 void Server::SendAddParticleSpawnerAll(u16 amount, float spawntime, v3f minpos, v3f maxpos,
3562         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3563         float minsize, float maxsize, bool collisiondetection, std::string texture, u32 id)
3564 {
3565         for(std::map<u16, RemoteClient*>::iterator
3566                 i = m_clients.begin();
3567                 i != m_clients.end(); i++)
3568         {
3569                 // Get client and check that it is valid
3570                 RemoteClient *client = i->second;
3571                 assert(client->peer_id == i->first);
3572                 if(client->serialization_version == SER_FMT_VER_INVALID)
3573                         continue;
3574
3575                 SendAddParticleSpawner(client->peer_id, amount, spawntime,
3576                         minpos, maxpos, minvel, maxvel, minacc, maxacc,
3577                         minexptime, maxexptime, minsize, maxsize, collisiondetection, texture, id);
3578         }
3579 }
3580
3581 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
3582 {
3583         DSTACK(__FUNCTION_NAME);
3584
3585         std::ostringstream os(std::ios_base::binary);
3586         writeU16(os, TOCLIENT_DELETE_PARTICLESPAWNER);
3587
3588         writeU16(os, id);
3589
3590         // Make data buffer
3591         std::string s = os.str();
3592         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3593         // Send as reliable
3594         m_con.Send(peer_id, 0, data, true);
3595 }
3596
3597 void Server::SendDeleteParticleSpawnerAll(u32 id)
3598 {
3599         for(std::map<u16, RemoteClient*>::iterator
3600                 i = m_clients.begin();
3601                 i != m_clients.end(); i++)
3602         {
3603                 // Get client and check that it is valid
3604                 RemoteClient *client = i->second;
3605                 assert(client->peer_id == i->first);
3606                 if(client->serialization_version == SER_FMT_VER_INVALID)
3607                         continue;
3608
3609                 SendDeleteParticleSpawner(client->peer_id, id);
3610         }
3611 }
3612
3613 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
3614 {
3615         std::ostringstream os(std::ios_base::binary);
3616
3617         // Write command
3618         writeU16(os, TOCLIENT_HUDADD);
3619         writeU32(os, id);
3620         writeU8(os, (u8)form->type);
3621         writeV2F1000(os, form->pos);
3622         os << serializeString(form->name);
3623         writeV2F1000(os, form->scale);
3624         os << serializeString(form->text);
3625         writeU32(os, form->number);
3626         writeU32(os, form->item);
3627         writeU32(os, form->dir);
3628         writeV2F1000(os, form->align);
3629         writeV2F1000(os, form->offset);
3630
3631         // Make data buffer
3632         std::string s = os.str();
3633         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3634         // Send as reliable
3635         m_con.Send(peer_id, 0, data, true);
3636 }
3637
3638 void Server::SendHUDRemove(u16 peer_id, u32 id)
3639 {
3640         std::ostringstream os(std::ios_base::binary);
3641
3642         // Write command
3643         writeU16(os, TOCLIENT_HUDRM);
3644         writeU32(os, id);
3645
3646         // Make data buffer
3647         std::string s = os.str();
3648         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3649         // Send as reliable
3650         m_con.Send(peer_id, 0, data, true);
3651 }
3652
3653 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
3654 {
3655         std::ostringstream os(std::ios_base::binary);
3656
3657         // Write command
3658         writeU16(os, TOCLIENT_HUDCHANGE);
3659         writeU32(os, id);
3660         writeU8(os, (u8)stat);
3661         switch (stat) {
3662                 case HUD_STAT_POS:
3663                 case HUD_STAT_SCALE:
3664                 case HUD_STAT_ALIGN:
3665                 case HUD_STAT_OFFSET:
3666                         writeV2F1000(os, *(v2f *)value);
3667                         break;
3668                 case HUD_STAT_NAME:
3669                 case HUD_STAT_TEXT:
3670                         os << serializeString(*(std::string *)value);
3671                         break;
3672                 case HUD_STAT_NUMBER:
3673                 case HUD_STAT_ITEM:
3674                 case HUD_STAT_DIR:
3675                 default:
3676                         writeU32(os, *(u32 *)value);
3677                         break;
3678         }
3679
3680         // Make data buffer
3681         std::string s = os.str();
3682         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3683         // Send as reliable
3684         m_con.Send(peer_id, 0, data, true);
3685 }
3686
3687 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
3688 {
3689         std::ostringstream os(std::ios_base::binary);
3690
3691         // Write command
3692         writeU16(os, TOCLIENT_HUD_SET_FLAGS);
3693         writeU32(os, flags);
3694         writeU32(os, mask);
3695
3696         // Make data buffer
3697         std::string s = os.str();
3698         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3699         // Send as reliable
3700         m_con.Send(peer_id, 0, data, true);
3701 }
3702
3703 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
3704 {
3705         std::ostringstream os(std::ios_base::binary);
3706
3707         // Write command
3708         writeU16(os, TOCLIENT_HUD_SET_PARAM);
3709         writeU16(os, param);
3710         os<<serializeString(value);
3711
3712         // Make data buffer
3713         std::string s = os.str();
3714         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3715         // Send as reliable
3716         m_con.Send(peer_id, 0, data, true);
3717 }
3718
3719 void Server::BroadcastChatMessage(const std::wstring &message)
3720 {
3721         for(std::map<u16, RemoteClient*>::iterator
3722                 i = m_clients.begin();
3723                 i != m_clients.end(); ++i)
3724         {
3725                 // Get client and check that it is valid
3726                 RemoteClient *client = i->second;
3727                 assert(client->peer_id == i->first);
3728                 if(client->serialization_version == SER_FMT_VER_INVALID)
3729                         continue;
3730
3731                 SendChatMessage(client->peer_id, message);
3732         }
3733 }
3734
3735 void Server::SendPlayerHP(u16 peer_id)
3736 {
3737         DSTACK(__FUNCTION_NAME);
3738         PlayerSAO *playersao = getPlayerSAO(peer_id);
3739         assert(playersao);
3740         playersao->m_hp_not_sent = false;
3741         SendHP(m_con, peer_id, playersao->getHP());
3742 }
3743
3744 void Server::SendMovePlayer(u16 peer_id)
3745 {
3746         DSTACK(__FUNCTION_NAME);
3747         Player *player = m_env->getPlayer(peer_id);
3748         assert(player);
3749
3750         std::ostringstream os(std::ios_base::binary);
3751         writeU16(os, TOCLIENT_MOVE_PLAYER);
3752         writeV3F1000(os, player->getPosition());
3753         writeF1000(os, player->getPitch());
3754         writeF1000(os, player->getYaw());
3755
3756         {
3757                 v3f pos = player->getPosition();
3758                 f32 pitch = player->getPitch();
3759                 f32 yaw = player->getYaw();
3760                 verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
3761                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3762                                 <<" pitch="<<pitch
3763                                 <<" yaw="<<yaw
3764                                 <<std::endl;
3765         }
3766
3767         // Make data buffer
3768         std::string s = os.str();
3769         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3770         // Send as reliable
3771         m_con.Send(peer_id, 0, data, true);
3772 }
3773
3774 void Server::SendPlayerPrivileges(u16 peer_id)
3775 {
3776         Player *player = m_env->getPlayer(peer_id);
3777         assert(player);
3778         if(player->peer_id == PEER_ID_INEXISTENT)
3779                 return;
3780
3781         std::set<std::string> privs;
3782         m_script->getAuth(player->getName(), NULL, &privs);
3783
3784         std::ostringstream os(std::ios_base::binary);
3785         writeU16(os, TOCLIENT_PRIVILEGES);
3786         writeU16(os, privs.size());
3787         for(std::set<std::string>::const_iterator i = privs.begin();
3788                         i != privs.end(); i++){
3789                 os<<serializeString(*i);
3790         }
3791
3792         // Make data buffer
3793         std::string s = os.str();
3794         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3795         // Send as reliable
3796         m_con.Send(peer_id, 0, data, true);
3797 }
3798
3799 void Server::SendPlayerInventoryFormspec(u16 peer_id)
3800 {
3801         Player *player = m_env->getPlayer(peer_id);
3802         assert(player);
3803         if(player->peer_id == PEER_ID_INEXISTENT)
3804                 return;
3805
3806         std::ostringstream os(std::ios_base::binary);
3807         writeU16(os, TOCLIENT_INVENTORY_FORMSPEC);
3808         os<<serializeLongString(player->inventory_formspec);
3809
3810         // Make data buffer
3811         std::string s = os.str();
3812         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3813         // Send as reliable
3814         m_con.Send(peer_id, 0, data, true);
3815 }
3816
3817 s32 Server::playSound(const SimpleSoundSpec &spec,
3818                 const ServerSoundParams &params)
3819 {
3820         // Find out initial position of sound
3821         bool pos_exists = false;
3822         v3f pos = params.getPos(m_env, &pos_exists);
3823         // If position is not found while it should be, cancel sound
3824         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
3825                 return -1;
3826         // Filter destination clients
3827         std::set<RemoteClient*> dst_clients;
3828         if(params.to_player != "")
3829         {
3830                 Player *player = m_env->getPlayer(params.to_player.c_str());
3831                 if(!player){
3832                         infostream<<"Server::playSound: Player \""<<params.to_player
3833                                         <<"\" not found"<<std::endl;
3834                         return -1;
3835                 }
3836                 if(player->peer_id == PEER_ID_INEXISTENT){
3837                         infostream<<"Server::playSound: Player \""<<params.to_player
3838                                         <<"\" not connected"<<std::endl;
3839                         return -1;
3840                 }
3841                 RemoteClient *client = getClient(player->peer_id);
3842                 dst_clients.insert(client);
3843         }
3844         else
3845         {
3846                 for(std::map<u16, RemoteClient*>::iterator
3847                                 i = m_clients.begin(); i != m_clients.end(); ++i)
3848                 {
3849                         RemoteClient *client = i->second;
3850                         Player *player = m_env->getPlayer(client->peer_id);
3851                         if(!player)
3852                                 continue;
3853                         if(pos_exists){
3854                                 if(player->getPosition().getDistanceFrom(pos) >
3855                                                 params.max_hear_distance)
3856                                         continue;
3857                         }
3858                         dst_clients.insert(client);
3859                 }
3860         }
3861         if(dst_clients.size() == 0)
3862                 return -1;
3863         // Create the sound
3864         s32 id = m_next_sound_id++;
3865         // The sound will exist as a reference in m_playing_sounds
3866         m_playing_sounds[id] = ServerPlayingSound();
3867         ServerPlayingSound &psound = m_playing_sounds[id];
3868         psound.params = params;
3869         for(std::set<RemoteClient*>::iterator i = dst_clients.begin();
3870                         i != dst_clients.end(); i++)
3871                 psound.clients.insert((*i)->peer_id);
3872         // Create packet
3873         std::ostringstream os(std::ios_base::binary);
3874         writeU16(os, TOCLIENT_PLAY_SOUND);
3875         writeS32(os, id);
3876         os<<serializeString(spec.name);
3877         writeF1000(os, spec.gain * params.gain);
3878         writeU8(os, params.type);
3879         writeV3F1000(os, pos);
3880         writeU16(os, params.object);
3881         writeU8(os, params.loop);
3882         // Make data buffer
3883         std::string s = os.str();
3884         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3885         // Send
3886         for(std::set<RemoteClient*>::iterator i = dst_clients.begin();
3887                         i != dst_clients.end(); i++){
3888                 // Send as reliable
3889                 m_con.Send((*i)->peer_id, 0, data, true);
3890         }
3891         return id;
3892 }
3893 void Server::stopSound(s32 handle)
3894 {
3895         // Get sound reference
3896         std::map<s32, ServerPlayingSound>::iterator i =
3897                         m_playing_sounds.find(handle);
3898         if(i == m_playing_sounds.end())
3899                 return;
3900         ServerPlayingSound &psound = i->second;
3901         // Create packet
3902         std::ostringstream os(std::ios_base::binary);
3903         writeU16(os, TOCLIENT_STOP_SOUND);
3904         writeS32(os, handle);
3905         // Make data buffer
3906         std::string s = os.str();
3907         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3908         // Send
3909         for(std::set<u16>::iterator i = psound.clients.begin();
3910                         i != psound.clients.end(); i++){
3911                 // Send as reliable
3912                 m_con.Send(*i, 0, data, true);
3913         }
3914         // Remove sound reference
3915         m_playing_sounds.erase(i);
3916 }
3917
3918 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
3919         std::list<u16> *far_players, float far_d_nodes)
3920 {
3921         float maxd = far_d_nodes*BS;
3922         v3f p_f = intToFloat(p, BS);
3923
3924         // Create packet
3925         u32 replysize = 8;
3926         SharedBuffer<u8> reply(replysize);
3927         writeU16(&reply[0], TOCLIENT_REMOVENODE);
3928         writeS16(&reply[2], p.X);
3929         writeS16(&reply[4], p.Y);
3930         writeS16(&reply[6], p.Z);
3931
3932         for(std::map<u16, RemoteClient*>::iterator
3933                 i = m_clients.begin();
3934                 i != m_clients.end(); ++i)
3935         {
3936                 // Get client and check that it is valid
3937                 RemoteClient *client = i->second;
3938                 assert(client->peer_id == i->first);
3939                 if(client->serialization_version == SER_FMT_VER_INVALID)
3940                         continue;
3941
3942                 // Don't send if it's the same one
3943                 if(client->peer_id == ignore_id)
3944                         continue;
3945
3946                 if(far_players)
3947                 {
3948                         // Get player
3949                         Player *player = m_env->getPlayer(client->peer_id);
3950                         if(player)
3951                         {
3952                                 // If player is far away, only set modified blocks not sent
3953                                 v3f player_pos = player->getPosition();
3954                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3955                                 {
3956                                         far_players->push_back(client->peer_id);
3957                                         continue;
3958                                 }
3959                         }
3960                 }
3961
3962                 // Send as reliable
3963                 m_con.Send(client->peer_id, 0, reply, true);
3964         }
3965 }
3966
3967 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
3968                 std::list<u16> *far_players, float far_d_nodes)
3969 {
3970         float maxd = far_d_nodes*BS;
3971         v3f p_f = intToFloat(p, BS);
3972
3973         for(std::map<u16, RemoteClient*>::iterator
3974                 i = m_clients.begin();
3975                 i != m_clients.end(); ++i)
3976         {
3977                 // Get client and check that it is valid
3978                 RemoteClient *client = i->second;
3979                 assert(client->peer_id == i->first);
3980                 if(client->serialization_version == SER_FMT_VER_INVALID)
3981                         continue;
3982
3983                 // Don't send if it's the same one
3984                 if(client->peer_id == ignore_id)
3985                         continue;
3986
3987                 if(far_players)
3988                 {
3989                         // Get player
3990                         Player *player = m_env->getPlayer(client->peer_id);
3991                         if(player)
3992                         {
3993                                 // If player is far away, only set modified blocks not sent
3994                                 v3f player_pos = player->getPosition();
3995                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3996                                 {
3997                                         far_players->push_back(client->peer_id);
3998                                         continue;
3999                                 }
4000                         }
4001                 }
4002
4003                 // Create packet
4004                 u32 replysize = 8 + MapNode::serializedLength(client->serialization_version);
4005                 SharedBuffer<u8> reply(replysize);
4006                 writeU16(&reply[0], TOCLIENT_ADDNODE);
4007                 writeS16(&reply[2], p.X);
4008                 writeS16(&reply[4], p.Y);
4009                 writeS16(&reply[6], p.Z);
4010                 n.serialize(&reply[8], client->serialization_version);
4011
4012                 // Send as reliable
4013                 m_con.Send(client->peer_id, 0, reply, true);
4014         }
4015 }
4016
4017 void Server::setBlockNotSent(v3s16 p)
4018 {
4019         for(std::map<u16, RemoteClient*>::iterator
4020                 i = m_clients.begin();
4021                 i != m_clients.end(); ++i)
4022         {
4023                 RemoteClient *client = i->second;
4024                 client->SetBlockNotSent(p);
4025         }
4026 }
4027
4028 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
4029 {
4030         DSTACK(__FUNCTION_NAME);
4031
4032         v3s16 p = block->getPos();
4033
4034 #if 0
4035         // Analyze it a bit
4036         bool completely_air = true;
4037         for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
4038         for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
4039         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
4040         {
4041                 if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
4042                 {
4043                         completely_air = false;
4044                         x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
4045                 }
4046         }
4047
4048         // Print result
4049         infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
4050         if(completely_air)
4051                 infostream<<"[completely air] ";
4052         infostream<<std::endl;
4053 #endif
4054
4055         /*
4056                 Create a packet with the block in the right format
4057         */
4058
4059         std::ostringstream os(std::ios_base::binary);
4060         block->serialize(os, ver, false);
4061         std::string s = os.str();
4062         SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
4063
4064         u32 replysize = 8 + blockdata.getSize();
4065         SharedBuffer<u8> reply(replysize);
4066         writeU16(&reply[0], TOCLIENT_BLOCKDATA);
4067         writeS16(&reply[2], p.X);
4068         writeS16(&reply[4], p.Y);
4069         writeS16(&reply[6], p.Z);
4070         memcpy(&reply[8], *blockdata, blockdata.getSize());
4071
4072         /*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
4073                         <<":  \tpacket size: "<<replysize<<std::endl;*/
4074
4075         /*
4076                 Send packet
4077         */
4078         m_con.Send(peer_id, 1, reply, true);
4079 }
4080
4081 void Server::SendBlocks(float dtime)
4082 {
4083         DSTACK(__FUNCTION_NAME);
4084
4085         JMutexAutoLock envlock(m_env_mutex);
4086         JMutexAutoLock conlock(m_con_mutex);
4087
4088         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
4089
4090         std::vector<PrioritySortedBlockTransfer> queue;
4091
4092         s32 total_sending = 0;
4093
4094         {
4095                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
4096
4097                 for(std::map<u16, RemoteClient*>::iterator
4098                         i = m_clients.begin();
4099                         i != m_clients.end(); ++i)
4100                 {
4101                         RemoteClient *client = i->second;
4102                         assert(client->peer_id == i->first);
4103
4104                         // If definitions and textures have not been sent, don't
4105                         // send MapBlocks either
4106                         if(!client->definitions_sent)
4107                                 continue;
4108
4109                         total_sending += client->SendingCount();
4110
4111                         if(client->serialization_version == SER_FMT_VER_INVALID)
4112                                 continue;
4113
4114                         client->GetNextBlocks(this, dtime, queue);
4115                 }
4116         }
4117
4118         // Sort.
4119         // Lowest priority number comes first.
4120         // Lowest is most important.
4121         std::sort(queue.begin(), queue.end());
4122
4123         for(u32 i=0; i<queue.size(); i++)
4124         {
4125                 //TODO: Calculate limit dynamically
4126                 if(total_sending >= g_settings->getS32
4127                                 ("max_simultaneous_block_sends_server_total"))
4128                         break;
4129
4130                 PrioritySortedBlockTransfer q = queue[i];
4131
4132                 MapBlock *block = NULL;
4133                 try
4134                 {
4135                         block = m_env->getMap().getBlockNoCreate(q.pos);
4136                 }
4137                 catch(InvalidPositionException &e)
4138                 {
4139                         continue;
4140                 }
4141
4142                 RemoteClient *client = getClient(q.peer_id);
4143
4144                 SendBlockNoLock(q.peer_id, block, client->serialization_version);
4145
4146                 client->SentBlock(q.pos);
4147
4148                 total_sending++;
4149         }
4150 }
4151
4152 void Server::fillMediaCache()
4153 {
4154         DSTACK(__FUNCTION_NAME);
4155
4156         infostream<<"Server: Calculating media file checksums"<<std::endl;
4157
4158         // Collect all media file paths
4159         std::list<std::string> paths;
4160         for(std::vector<ModSpec>::iterator i = m_mods.begin();
4161                         i != m_mods.end(); i++){
4162                 const ModSpec &mod = *i;
4163                 paths.push_back(mod.path + DIR_DELIM + "textures");
4164                 paths.push_back(mod.path + DIR_DELIM + "sounds");
4165                 paths.push_back(mod.path + DIR_DELIM + "media");
4166                 paths.push_back(mod.path + DIR_DELIM + "models");
4167         }
4168         std::string path_all = "textures";
4169         paths.push_back(path_all + DIR_DELIM + "all");
4170
4171         // Collect media file information from paths into cache
4172         for(std::list<std::string>::iterator i = paths.begin();
4173                         i != paths.end(); i++)
4174         {
4175                 std::string mediapath = *i;
4176                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
4177                 for(u32 j=0; j<dirlist.size(); j++){
4178                         if(dirlist[j].dir) // Ignode dirs
4179                                 continue;
4180                         std::string filename = dirlist[j].name;
4181                         // If name contains illegal characters, ignore the file
4182                         if(!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)){
4183                                 infostream<<"Server: ignoring illegal file name: \""
4184                                                 <<filename<<"\""<<std::endl;
4185                                 continue;
4186                         }
4187                         // If name is not in a supported format, ignore it
4188                         const char *supported_ext[] = {
4189                                 ".png", ".jpg", ".bmp", ".tga",
4190                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
4191                                 ".ogg",
4192                                 ".x", ".b3d", ".md2", ".obj",
4193                                 NULL
4194                         };
4195                         if(removeStringEnd(filename, supported_ext) == ""){
4196                                 infostream<<"Server: ignoring unsupported file extension: \""
4197                                                 <<filename<<"\""<<std::endl;
4198                                 continue;
4199                         }
4200                         // Ok, attempt to load the file and add to cache
4201                         std::string filepath = mediapath + DIR_DELIM + filename;
4202                         // Read data
4203                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
4204                         if(fis.good() == false){
4205                                 errorstream<<"Server::fillMediaCache(): Could not open \""
4206                                                 <<filename<<"\" for reading"<<std::endl;
4207                                 continue;
4208                         }
4209                         std::ostringstream tmp_os(std::ios_base::binary);
4210                         bool bad = false;
4211                         for(;;){
4212                                 char buf[1024];
4213                                 fis.read(buf, 1024);
4214                                 std::streamsize len = fis.gcount();
4215                                 tmp_os.write(buf, len);
4216                                 if(fis.eof())
4217                                         break;
4218                                 if(!fis.good()){
4219                                         bad = true;
4220                                         break;
4221                                 }
4222                         }
4223                         if(bad){
4224                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
4225                                                 <<filename<<"\""<<std::endl;
4226                                 continue;
4227                         }
4228                         if(tmp_os.str().length() == 0){
4229                                 errorstream<<"Server::fillMediaCache(): Empty file \""
4230                                                 <<filepath<<"\""<<std::endl;
4231                                 continue;
4232                         }
4233
4234                         SHA1 sha1;
4235                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
4236
4237                         unsigned char *digest = sha1.getDigest();
4238                         std::string sha1_base64 = base64_encode(digest, 20);
4239                         std::string sha1_hex = hex_encode((char*)digest, 20);
4240                         free(digest);
4241
4242                         // Put in list
4243                         this->m_media[filename] = MediaInfo(filepath, sha1_base64);
4244                         verbosestream<<"Server: "<<sha1_hex<<" is "<<filename<<std::endl;
4245                 }
4246         }
4247 }
4248
4249 struct SendableMediaAnnouncement
4250 {
4251         std::string name;
4252         std::string sha1_digest;
4253
4254         SendableMediaAnnouncement(const std::string name_="",
4255                         const std::string sha1_digest_=""):
4256                 name(name_),
4257                 sha1_digest(sha1_digest_)
4258         {}
4259 };
4260
4261 void Server::sendMediaAnnouncement(u16 peer_id)
4262 {
4263         DSTACK(__FUNCTION_NAME);
4264
4265         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
4266                         <<std::endl;
4267
4268         std::list<SendableMediaAnnouncement> file_announcements;
4269
4270         for(std::map<std::string, MediaInfo>::iterator i = m_media.begin();
4271                         i != m_media.end(); i++){
4272                 // Put in list
4273                 file_announcements.push_back(
4274                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
4275         }
4276
4277         // Make packet
4278         std::ostringstream os(std::ios_base::binary);
4279
4280         /*
4281                 u16 command
4282                 u32 number of files
4283                 for each texture {
4284                         u16 length of name
4285                         string name
4286                         u16 length of sha1_digest
4287                         string sha1_digest
4288                 }
4289         */
4290
4291         writeU16(os, TOCLIENT_ANNOUNCE_MEDIA);
4292         writeU16(os, file_announcements.size());
4293
4294         for(std::list<SendableMediaAnnouncement>::iterator
4295                         j = file_announcements.begin();
4296                         j != file_announcements.end(); ++j){
4297                 os<<serializeString(j->name);
4298                 os<<serializeString(j->sha1_digest);
4299         }
4300         os<<serializeString(g_settings->get("remote_media"));
4301
4302         // Make data buffer
4303         std::string s = os.str();
4304         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4305
4306         // Send as reliable
4307         m_con.Send(peer_id, 0, data, true);
4308 }
4309
4310 struct SendableMedia
4311 {
4312         std::string name;
4313         std::string path;
4314         std::string data;
4315
4316         SendableMedia(const std::string &name_="", const std::string path_="",
4317                         const std::string &data_=""):
4318                 name(name_),
4319                 path(path_),
4320                 data(data_)
4321         {}
4322 };
4323
4324 void Server::sendRequestedMedia(u16 peer_id,
4325                 const std::list<MediaRequest> &tosend)
4326 {
4327         DSTACK(__FUNCTION_NAME);
4328
4329         verbosestream<<"Server::sendRequestedMedia(): "
4330                         <<"Sending files to client"<<std::endl;
4331
4332         /* Read files */
4333
4334         // Put 5kB in one bunch (this is not accurate)
4335         u32 bytes_per_bunch = 5000;
4336
4337         std::vector< std::list<SendableMedia> > file_bunches;
4338         file_bunches.push_back(std::list<SendableMedia>());
4339
4340         u32 file_size_bunch_total = 0;
4341
4342         for(std::list<MediaRequest>::const_iterator i = tosend.begin();
4343                         i != tosend.end(); ++i)
4344         {
4345                 if(m_media.find(i->name) == m_media.end()){
4346                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
4347                                         <<"unknown file \""<<(i->name)<<"\""<<std::endl;
4348                         continue;
4349                 }
4350
4351                 //TODO get path + name
4352                 std::string tpath = m_media[(*i).name].path;
4353
4354                 // Read data
4355                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
4356                 if(fis.good() == false){
4357                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
4358                                         <<tpath<<"\" for reading"<<std::endl;
4359                         continue;
4360                 }
4361                 std::ostringstream tmp_os(std::ios_base::binary);
4362                 bool bad = false;
4363                 for(;;){
4364                         char buf[1024];
4365                         fis.read(buf, 1024);
4366                         std::streamsize len = fis.gcount();
4367                         tmp_os.write(buf, len);
4368                         file_size_bunch_total += len;
4369                         if(fis.eof())
4370                                 break;
4371                         if(!fis.good()){
4372                                 bad = true;
4373                                 break;
4374                         }
4375                 }
4376                 if(bad){
4377                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
4378                                         <<(*i).name<<"\""<<std::endl;
4379                         continue;
4380                 }
4381                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
4382                                 <<tname<<"\""<<std::endl;*/
4383                 // Put in list
4384                 file_bunches[file_bunches.size()-1].push_back(
4385                                 SendableMedia((*i).name, tpath, tmp_os.str()));
4386
4387                 // Start next bunch if got enough data
4388                 if(file_size_bunch_total >= bytes_per_bunch){
4389                         file_bunches.push_back(std::list<SendableMedia>());
4390                         file_size_bunch_total = 0;
4391                 }
4392
4393         }
4394
4395         /* Create and send packets */
4396
4397         u32 num_bunches = file_bunches.size();
4398         for(u32 i=0; i<num_bunches; i++)
4399         {
4400                 std::ostringstream os(std::ios_base::binary);
4401
4402                 /*
4403                         u16 command
4404                         u16 total number of texture bunches
4405                         u16 index of this bunch
4406                         u32 number of files in this bunch
4407                         for each file {
4408                                 u16 length of name
4409                                 string name
4410                                 u32 length of data
4411                                 data
4412                         }
4413                 */
4414
4415                 writeU16(os, TOCLIENT_MEDIA);
4416                 writeU16(os, num_bunches);
4417                 writeU16(os, i);
4418                 writeU32(os, file_bunches[i].size());
4419
4420                 for(std::list<SendableMedia>::iterator
4421                                 j = file_bunches[i].begin();
4422                                 j != file_bunches[i].end(); ++j){
4423                         os<<serializeString(j->name);
4424                         os<<serializeLongString(j->data);
4425                 }
4426
4427                 // Make data buffer
4428                 std::string s = os.str();
4429                 verbosestream<<"Server::sendRequestedMedia(): bunch "
4430                                 <<i<<"/"<<num_bunches
4431                                 <<" files="<<file_bunches[i].size()
4432                                 <<" size=" <<s.size()<<std::endl;
4433                 SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4434                 // Send as reliable
4435                 m_con.Send(peer_id, 0, data, true);
4436         }
4437 }
4438
4439 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
4440 {
4441         if(m_detached_inventories.count(name) == 0){
4442                 errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
4443                 return;
4444         }
4445         Inventory *inv = m_detached_inventories[name];
4446
4447         std::ostringstream os(std::ios_base::binary);
4448         writeU16(os, TOCLIENT_DETACHED_INVENTORY);
4449         os<<serializeString(name);
4450         inv->serialize(os);
4451
4452         // Make data buffer
4453         std::string s = os.str();
4454         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4455         // Send as reliable
4456         m_con.Send(peer_id, 0, data, true);
4457 }
4458
4459 void Server::sendDetachedInventoryToAll(const std::string &name)
4460 {
4461         DSTACK(__FUNCTION_NAME);
4462
4463         for(std::map<u16, RemoteClient*>::iterator
4464                         i = m_clients.begin();
4465                         i != m_clients.end(); ++i){
4466                 RemoteClient *client = i->second;
4467                 sendDetachedInventory(name, client->peer_id);
4468         }
4469 }
4470
4471 void Server::sendDetachedInventories(u16 peer_id)
4472 {
4473         DSTACK(__FUNCTION_NAME);
4474
4475         for(std::map<std::string, Inventory*>::iterator
4476                         i = m_detached_inventories.begin();
4477                         i != m_detached_inventories.end(); i++){
4478                 const std::string &name = i->first;
4479                 //Inventory *inv = i->second;
4480                 sendDetachedInventory(name, peer_id);
4481         }
4482 }
4483
4484 /*
4485         Something random
4486 */
4487
4488 void Server::DiePlayer(u16 peer_id)
4489 {
4490         DSTACK(__FUNCTION_NAME);
4491
4492         PlayerSAO *playersao = getPlayerSAO(peer_id);
4493         assert(playersao);
4494
4495         infostream<<"Server::DiePlayer(): Player "
4496                         <<playersao->getPlayer()->getName()
4497                         <<" dies"<<std::endl;
4498
4499         playersao->setHP(0);
4500
4501         // Trigger scripted stuff
4502         m_script->on_dieplayer(playersao);
4503
4504         SendPlayerHP(peer_id);
4505         SendDeathscreen(m_con, peer_id, false, v3f(0,0,0));
4506 }
4507
4508 void Server::RespawnPlayer(u16 peer_id)
4509 {
4510         DSTACK(__FUNCTION_NAME);
4511
4512         PlayerSAO *playersao = getPlayerSAO(peer_id);
4513         assert(playersao);
4514
4515         infostream<<"Server::RespawnPlayer(): Player "
4516                         <<playersao->getPlayer()->getName()
4517                         <<" respawns"<<std::endl;
4518
4519         playersao->setHP(PLAYER_MAX_HP);
4520
4521         bool repositioned = m_script->on_respawnplayer(playersao);
4522         if(!repositioned){
4523                 v3f pos = findSpawnPos(m_env->getServerMap());
4524                 playersao->setPos(pos);
4525         }
4526 }
4527
4528 void Server::UpdateCrafting(u16 peer_id)
4529 {
4530         DSTACK(__FUNCTION_NAME);
4531
4532         Player* player = m_env->getPlayer(peer_id);
4533         assert(player);
4534
4535         // Get a preview for crafting
4536         ItemStack preview;
4537         getCraftingResult(&player->inventory, preview, false, this);
4538
4539         // Put the new preview in
4540         InventoryList *plist = player->inventory.getList("craftpreview");
4541         assert(plist);
4542         assert(plist->getSize() >= 1);
4543         plist->changeItem(0, preview);
4544 }
4545
4546 RemoteClient* Server::getClient(u16 peer_id)
4547 {
4548         DSTACK(__FUNCTION_NAME);
4549         //JMutexAutoLock lock(m_con_mutex);
4550         std::map<u16, RemoteClient*>::iterator n;
4551         n = m_clients.find(peer_id);
4552         // A client should exist for all peers
4553         assert(n != m_clients.end());
4554         return n->second;
4555 }
4556
4557 std::wstring Server::getStatusString()
4558 {
4559         std::wostringstream os(std::ios_base::binary);
4560         os<<L"# Server: ";
4561         // Version
4562         os<<L"version="<<narrow_to_wide(VERSION_STRING);
4563         // Uptime
4564         os<<L", uptime="<<m_uptime.get();
4565         // Information about clients
4566         std::map<u16, RemoteClient*>::iterator i;
4567         bool first;
4568         os<<L", clients={";
4569         for(i = m_clients.begin(), first = true;
4570                 i != m_clients.end(); ++i)
4571         {
4572                 // Get client and check that it is valid
4573                 RemoteClient *client = i->second;
4574                 assert(client->peer_id == i->first);
4575                 if(client->serialization_version == SER_FMT_VER_INVALID)
4576                         continue;
4577                 // Get player
4578                 Player *player = m_env->getPlayer(client->peer_id);
4579                 // Get name of player
4580                 std::wstring name = L"unknown";
4581                 if(player != NULL)
4582                         name = narrow_to_wide(player->getName());
4583                 // Add name to information string
4584                 if(!first)
4585                         os<<L",";
4586                 else
4587                         first = false;
4588                 os<<name;
4589         }
4590         os<<L"}";
4591         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
4592                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
4593         if(g_settings->get("motd") != "")
4594                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
4595         return os.str();
4596 }
4597
4598 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
4599 {
4600         std::set<std::string> privs;
4601         m_script->getAuth(name, NULL, &privs);
4602         return privs;
4603 }
4604
4605 bool Server::checkPriv(const std::string &name, const std::string &priv)
4606 {
4607         std::set<std::string> privs = getPlayerEffectivePrivs(name);
4608         return (privs.count(priv) != 0);
4609 }
4610
4611 void Server::reportPrivsModified(const std::string &name)
4612 {
4613         if(name == ""){
4614                 for(std::map<u16, RemoteClient*>::iterator
4615                                 i = m_clients.begin();
4616                                 i != m_clients.end(); ++i){
4617                         RemoteClient *client = i->second;
4618                         Player *player = m_env->getPlayer(client->peer_id);
4619                         reportPrivsModified(player->getName());
4620                 }
4621         } else {
4622                 Player *player = m_env->getPlayer(name.c_str());
4623                 if(!player)
4624                         return;
4625                 SendPlayerPrivileges(player->peer_id);
4626                 PlayerSAO *sao = player->getPlayerSAO();
4627                 if(!sao)
4628                         return;
4629                 sao->updatePrivileges(
4630                                 getPlayerEffectivePrivs(name),
4631                                 isSingleplayer());
4632         }
4633 }
4634
4635 void Server::reportInventoryFormspecModified(const std::string &name)
4636 {
4637         Player *player = m_env->getPlayer(name.c_str());
4638         if(!player)
4639                 return;
4640         SendPlayerInventoryFormspec(player->peer_id);
4641 }
4642
4643 // Saves g_settings to configpath given at initialization
4644 void Server::saveConfig()
4645 {
4646         if(m_path_config != "")
4647                 g_settings->updateConfigFile(m_path_config.c_str());
4648 }
4649
4650 void Server::notifyPlayer(const char *name, const std::wstring msg, const bool prepend = true)
4651 {
4652         Player *player = m_env->getPlayer(name);
4653         if(!player)
4654                 return;
4655         if (prepend)
4656                 SendChatMessage(player->peer_id, std::wstring(L"Server -!- ")+msg);
4657         else
4658                 SendChatMessage(player->peer_id, msg);
4659 }
4660
4661 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
4662 {
4663         Player *player = m_env->getPlayer(playername);
4664
4665         if(!player)
4666         {
4667                 infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
4668                 return false;
4669         }
4670
4671         SendShowFormspecMessage(player->peer_id, formspec, formname);
4672         return true;
4673 }
4674
4675 u32 Server::hudAdd(Player *player, HudElement *form) {
4676         if (!player)
4677                 return -1;
4678
4679         u32 id = hud_get_free_id(player);
4680         if (id < player->hud.size())
4681                 player->hud[id] = form;
4682         else
4683                 player->hud.push_back(form);
4684         
4685         SendHUDAdd(player->peer_id, id, form);
4686         return id;
4687 }
4688
4689 bool Server::hudRemove(Player *player, u32 id) {
4690         if (!player || id >= player->hud.size() || !player->hud[id])
4691                 return false;
4692
4693         delete player->hud[id];
4694         player->hud[id] = NULL;
4695         
4696         SendHUDRemove(player->peer_id, id);
4697         return true;
4698 }
4699
4700 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
4701         if (!player)
4702                 return false;
4703
4704         SendHUDChange(player->peer_id, id, stat, data);
4705         return true;
4706 }
4707
4708 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
4709         if (!player)
4710                 return false;
4711
4712         SendHUDSetFlags(player->peer_id, flags, mask);
4713         return true;
4714 }
4715
4716 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
4717         if (!player)
4718                 return false;
4719         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
4720                 return false;
4721
4722         std::ostringstream os(std::ios::binary);
4723         writeS32(os, hotbar_itemcount);
4724         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
4725         return true;
4726 }
4727
4728 void Server::notifyPlayers(const std::wstring msg)
4729 {
4730         BroadcastChatMessage(msg);
4731 }
4732
4733 void Server::spawnParticle(const char *playername, v3f pos,
4734                 v3f velocity, v3f acceleration,
4735                 float expirationtime, float size, bool
4736                 collisiondetection, std::string texture)
4737 {
4738         Player *player = m_env->getPlayer(playername);
4739         if(!player)
4740                 return;
4741         SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
4742                         expirationtime, size, collisiondetection, texture);
4743 }
4744
4745 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
4746                 float expirationtime, float size,
4747                 bool collisiondetection, std::string texture)
4748 {
4749         SendSpawnParticleAll(pos, velocity, acceleration,
4750                         expirationtime, size, collisiondetection, texture);
4751 }
4752
4753 u32 Server::addParticleSpawner(const char *playername,
4754                 u16 amount, float spawntime,
4755                 v3f minpos, v3f maxpos,
4756                 v3f minvel, v3f maxvel,
4757                 v3f minacc, v3f maxacc,
4758                 float minexptime, float maxexptime,
4759                 float minsize, float maxsize,
4760                 bool collisiondetection, std::string texture)
4761 {
4762         Player *player = m_env->getPlayer(playername);
4763         if(!player)
4764                 return -1;
4765
4766         u32 id = 0;
4767         for(;;) // look for unused particlespawner id
4768         {
4769                 id++;
4770                 if (std::find(m_particlespawner_ids.begin(),
4771                                 m_particlespawner_ids.end(), id)
4772                                 == m_particlespawner_ids.end())
4773                 {
4774                         m_particlespawner_ids.push_back(id);
4775                         break;
4776                 }
4777         }
4778
4779         SendAddParticleSpawner(player->peer_id, amount, spawntime,
4780                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
4781                 minexptime, maxexptime, minsize, maxsize,
4782                 collisiondetection, texture, id);
4783
4784         return id;
4785 }
4786
4787 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
4788                 v3f minpos, v3f maxpos,
4789                 v3f minvel, v3f maxvel,
4790                 v3f minacc, v3f maxacc,
4791                 float minexptime, float maxexptime,
4792                 float minsize, float maxsize,
4793                 bool collisiondetection, std::string texture)
4794 {
4795         u32 id = 0;
4796         for(;;) // look for unused particlespawner id
4797         {
4798                 id++;
4799                 if (std::find(m_particlespawner_ids.begin(),
4800                                 m_particlespawner_ids.end(), id)
4801                                 == m_particlespawner_ids.end())
4802                 {
4803                         m_particlespawner_ids.push_back(id);
4804                         break;
4805                 }
4806         }
4807
4808         SendAddParticleSpawnerAll(amount, spawntime,
4809                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
4810                 minexptime, maxexptime, minsize, maxsize,
4811                 collisiondetection, texture, id);
4812
4813         return id;
4814 }
4815
4816 void Server::deleteParticleSpawner(const char *playername, u32 id)
4817 {
4818         Player *player = m_env->getPlayer(playername);
4819         if(!player)
4820                 return;
4821
4822         m_particlespawner_ids.erase(
4823                         std::remove(m_particlespawner_ids.begin(),
4824                         m_particlespawner_ids.end(), id),
4825                         m_particlespawner_ids.end());
4826         SendDeleteParticleSpawner(player->peer_id, id);
4827 }
4828
4829 void Server::deleteParticleSpawnerAll(u32 id)
4830 {
4831         m_particlespawner_ids.erase(
4832                         std::remove(m_particlespawner_ids.begin(),
4833                         m_particlespawner_ids.end(), id),
4834                         m_particlespawner_ids.end());
4835         SendDeleteParticleSpawnerAll(id);
4836 }
4837
4838 void Server::queueBlockEmerge(v3s16 blockpos, bool allow_generate)
4839 {
4840         m_emerge->enqueueBlockEmerge(PEER_ID_INEXISTENT, blockpos, allow_generate);
4841 }
4842
4843 Inventory* Server::createDetachedInventory(const std::string &name)
4844 {
4845         if(m_detached_inventories.count(name) > 0){
4846                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
4847                 delete m_detached_inventories[name];
4848         } else {
4849                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
4850         }
4851         Inventory *inv = new Inventory(m_itemdef);
4852         assert(inv);
4853         m_detached_inventories[name] = inv;
4854         sendDetachedInventoryToAll(name);
4855         return inv;
4856 }
4857
4858 class BoolScopeSet
4859 {
4860 public:
4861         BoolScopeSet(bool *dst, bool val):
4862                 m_dst(dst)
4863         {
4864                 m_orig_state = *m_dst;
4865                 *m_dst = val;
4866         }
4867         ~BoolScopeSet()
4868         {
4869                 *m_dst = m_orig_state;
4870         }
4871 private:
4872         bool *m_dst;
4873         bool m_orig_state;
4874 };
4875
4876 // actions: time-reversed list
4877 // Return value: success/failure
4878 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
4879                 std::list<std::string> *log)
4880 {
4881         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
4882         ServerMap *map = (ServerMap*)(&m_env->getMap());
4883         // Disable rollback report sink while reverting
4884         BoolScopeSet rollback_scope_disable(&m_rollback_sink_enabled, false);
4885
4886         // Fail if no actions to handle
4887         if(actions.empty()){
4888                 log->push_back("Nothing to do.");
4889                 return false;
4890         }
4891
4892         int num_tried = 0;
4893         int num_failed = 0;
4894
4895         for(std::list<RollbackAction>::const_iterator
4896                         i = actions.begin();
4897                         i != actions.end(); i++)
4898         {
4899                 const RollbackAction &action = *i;
4900                 num_tried++;
4901                 bool success = action.applyRevert(map, this, this);
4902                 if(!success){
4903                         num_failed++;
4904                         std::ostringstream os;
4905                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
4906                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
4907                         if(log)
4908                                 log->push_back(os.str());
4909                 }else{
4910                         std::ostringstream os;
4911                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
4912                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
4913                         if(log)
4914                                 log->push_back(os.str());
4915                 }
4916         }
4917
4918         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
4919                         <<" failed"<<std::endl;
4920
4921         // Call it done if less than half failed
4922         return num_failed <= num_tried/2;
4923 }
4924
4925 // IGameDef interface
4926 // Under envlock
4927 IItemDefManager* Server::getItemDefManager()
4928 {
4929         return m_itemdef;
4930 }
4931 INodeDefManager* Server::getNodeDefManager()
4932 {
4933         return m_nodedef;
4934 }
4935 ICraftDefManager* Server::getCraftDefManager()
4936 {
4937         return m_craftdef;
4938 }
4939 ITextureSource* Server::getTextureSource()
4940 {
4941         return NULL;
4942 }
4943 IShaderSource* Server::getShaderSource()
4944 {
4945         return NULL;
4946 }
4947 u16 Server::allocateUnknownNodeId(const std::string &name)
4948 {
4949         return m_nodedef->allocateDummy(name);
4950 }
4951 ISoundManager* Server::getSoundManager()
4952 {
4953         return &dummySoundManager;
4954 }
4955 MtEventManager* Server::getEventManager()
4956 {
4957         return m_event;
4958 }
4959 IRollbackReportSink* Server::getRollbackReportSink()
4960 {
4961         if(!m_enable_rollback_recording)
4962                 return NULL;
4963         if(!m_rollback_sink_enabled)
4964                 return NULL;
4965         return m_rollback;
4966 }
4967
4968 IWritableItemDefManager* Server::getWritableItemDefManager()
4969 {
4970         return m_itemdef;
4971 }
4972 IWritableNodeDefManager* Server::getWritableNodeDefManager()
4973 {
4974         return m_nodedef;
4975 }
4976 IWritableCraftDefManager* Server::getWritableCraftDefManager()
4977 {
4978         return m_craftdef;
4979 }
4980
4981 const ModSpec* Server::getModSpec(const std::string &modname)
4982 {
4983         for(std::vector<ModSpec>::iterator i = m_mods.begin();
4984                         i != m_mods.end(); i++){
4985                 const ModSpec &mod = *i;
4986                 if(mod.name == modname)
4987                         return &mod;
4988         }
4989         return NULL;
4990 }
4991 void Server::getModNames(std::list<std::string> &modlist)
4992 {
4993         for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++)
4994         {
4995                 modlist.push_back(i->name);
4996         }
4997 }
4998 std::string Server::getBuiltinLuaPath()
4999 {
5000         return porting::path_share + DIR_DELIM + "builtin";
5001 }
5002
5003 v3f findSpawnPos(ServerMap &map)
5004 {
5005         //return v3f(50,50,50)*BS;
5006
5007         v3s16 nodepos;
5008
5009 #if 0
5010         nodepos = v2s16(0,0);
5011         groundheight = 20;
5012 #endif
5013
5014 #if 1
5015         s16 water_level = map.m_mgparams->water_level;
5016
5017         // Try to find a good place a few times
5018         for(s32 i=0; i<1000; i++)
5019         {
5020                 s32 range = 1 + i;
5021                 // We're going to try to throw the player to this position
5022                 v2s16 nodepos2d = v2s16(
5023                                 -range + (myrand() % (range * 2)),
5024                                 -range + (myrand() % (range * 2)));
5025
5026                 // Get ground height at point
5027                 s16 groundheight = map.findGroundLevel(nodepos2d);
5028                 if (groundheight <= water_level) // Don't go underwater
5029                         continue;
5030                 if (groundheight > water_level + 6) // Don't go to high places
5031                         continue;
5032
5033                 nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
5034                 bool is_good = false;
5035                 s32 air_count = 0;
5036                 for (s32 i = 0; i < 10; i++) {
5037                         v3s16 blockpos = getNodeBlockPos(nodepos);
5038                         map.emergeBlock(blockpos, true);
5039                         content_t c = map.getNodeNoEx(nodepos).getContent();
5040                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
5041                                 air_count++;
5042                                 if (air_count >= 2){
5043                                         is_good = true;
5044                                         break;
5045                                 }
5046                         }
5047                         nodepos.Y++;
5048                 }
5049                 if(is_good){
5050                         // Found a good place
5051                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
5052                         break;
5053                 }
5054         }
5055 #endif
5056
5057         return intToFloat(nodepos, BS);
5058 }
5059
5060 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
5061 {
5062         RemotePlayer *player = NULL;
5063         bool newplayer = false;
5064
5065         /*
5066                 Try to get an existing player
5067         */
5068         player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
5069
5070         // If player is already connected, cancel
5071         if(player != NULL && player->peer_id != 0)
5072         {
5073                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
5074                 return NULL;
5075         }
5076
5077         /*
5078                 If player with the wanted peer_id already exists, cancel.
5079         */
5080         if(m_env->getPlayer(peer_id) != NULL)
5081         {
5082                 infostream<<"emergePlayer(): Player with wrong name but same"
5083                                 " peer_id already exists"<<std::endl;
5084                 return NULL;
5085         }
5086
5087         /*
5088                 Create a new player if it doesn't exist yet
5089         */
5090         if(player == NULL)
5091         {
5092                 newplayer = true;
5093                 player = new RemotePlayer(this);
5094                 player->updateName(name);
5095
5096                 /* Set player position */
5097                 infostream<<"Server: Finding spawn place for player \""
5098                                 <<name<<"\""<<std::endl;
5099                 v3f pos = findSpawnPos(m_env->getServerMap());
5100                 player->setPosition(pos);
5101
5102                 /* Add player to environment */
5103                 m_env->addPlayer(player);
5104         }
5105
5106         /*
5107                 Create a new player active object
5108         */
5109         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
5110                         getPlayerEffectivePrivs(player->getName()),
5111                         isSingleplayer());
5112
5113         /* Clean up old HUD elements from previous sessions */
5114         player->hud.clear();
5115
5116         /* Add object to environment */
5117         m_env->addActiveObject(playersao);
5118
5119         /* Run scripts */
5120         if(newplayer)
5121                 m_script->on_newplayer(playersao);
5122
5123         m_script->on_joinplayer(playersao);
5124
5125         return playersao;
5126 }
5127
5128 void Server::handlePeerChange(PeerChange &c)
5129 {
5130         JMutexAutoLock envlock(m_env_mutex);
5131         JMutexAutoLock conlock(m_con_mutex);
5132
5133         if(c.type == PEER_ADDED)
5134         {
5135                 /*
5136                         Add
5137                 */
5138
5139                 // Error check
5140                 std::map<u16, RemoteClient*>::iterator n;
5141                 n = m_clients.find(c.peer_id);
5142                 // The client shouldn't already exist
5143                 assert(n == m_clients.end());
5144
5145                 // Create client
5146                 RemoteClient *client = new RemoteClient();
5147                 client->peer_id = c.peer_id;
5148                 m_clients[client->peer_id] = client;
5149
5150         } // PEER_ADDED
5151         else if(c.type == PEER_REMOVED)
5152         {
5153                 /*
5154                         Delete
5155                 */
5156
5157                 // Error check
5158                 std::map<u16, RemoteClient*>::iterator n;
5159                 n = m_clients.find(c.peer_id);
5160                 // The client should exist
5161                 assert(n != m_clients.end());
5162
5163                 /*
5164                         Mark objects to be not known by the client
5165                 */
5166                 RemoteClient *client = n->second;
5167                 // Handle objects
5168                 for(std::set<u16>::iterator
5169                                 i = client->m_known_objects.begin();
5170                                 i != client->m_known_objects.end(); ++i)
5171                 {
5172                         // Get object
5173                         u16 id = *i;
5174                         ServerActiveObject* obj = m_env->getActiveObject(id);
5175
5176                         if(obj && obj->m_known_by_count > 0)
5177                                 obj->m_known_by_count--;
5178                 }
5179
5180                 /*
5181                         Clear references to playing sounds
5182                 */
5183                 for(std::map<s32, ServerPlayingSound>::iterator
5184                                 i = m_playing_sounds.begin();
5185                                 i != m_playing_sounds.end();)
5186                 {
5187                         ServerPlayingSound &psound = i->second;
5188                         psound.clients.erase(c.peer_id);
5189                         if(psound.clients.size() == 0)
5190                                 m_playing_sounds.erase(i++);
5191                         else
5192                                 i++;
5193                 }
5194
5195                 Player *player = m_env->getPlayer(c.peer_id);
5196
5197                 // Collect information about leaving in chat
5198                 std::wstring message;
5199                 {
5200                         if(player != NULL)
5201                         {
5202                                 std::wstring name = narrow_to_wide(player->getName());
5203                                 message += L"*** ";
5204                                 message += name;
5205                                 message += L" left the game.";
5206                                 if(c.timeout)
5207                                         message += L" (timed out)";
5208                         }
5209                 }
5210
5211                 /* Run scripts and remove from environment */
5212                 {
5213                         if(player != NULL)
5214                         {
5215                                 PlayerSAO *playersao = player->getPlayerSAO();
5216                                 assert(playersao);
5217
5218                                 m_script->on_leaveplayer(playersao);
5219
5220                                 playersao->disconnected();
5221                         }
5222                 }
5223
5224                 /*
5225                         Print out action
5226                 */
5227                 {
5228                         if(player != NULL)
5229                         {
5230                                 std::ostringstream os(std::ios_base::binary);
5231                                 for(std::map<u16, RemoteClient*>::iterator
5232                                         i = m_clients.begin();
5233                                         i != m_clients.end(); ++i)
5234                                 {
5235                                         RemoteClient *client = i->second;
5236                                         assert(client->peer_id == i->first);
5237                                         if(client->serialization_version == SER_FMT_VER_INVALID)
5238                                                 continue;
5239                                         // Get player
5240                                         Player *player = m_env->getPlayer(client->peer_id);
5241                                         if(!player)
5242                                                 continue;
5243                                         // Get name of player
5244                                         os<<player->getName()<<" ";
5245                                 }
5246
5247                                 actionstream<<player->getName()<<" "
5248                                                 <<(c.timeout?"times out.":"leaves game.")
5249                                                 <<" List of players: "
5250                                                 <<os.str()<<std::endl;
5251                         }
5252                 }
5253
5254                 // Delete client
5255                 delete m_clients[c.peer_id];
5256                 m_clients.erase(c.peer_id);
5257
5258                 // Send player info to all remaining clients
5259                 //SendPlayerInfos();
5260
5261                 // Send leave chat message to all remaining clients
5262                 if(message.length() != 0)
5263                         BroadcastChatMessage(message);
5264
5265         } // PEER_REMOVED
5266         else
5267         {
5268                 assert(0);
5269         }
5270 }
5271
5272 void Server::handlePeerChanges()
5273 {
5274         while(m_peer_change_queue.size() > 0)
5275         {
5276                 PeerChange c = m_peer_change_queue.pop_front();
5277
5278                 verbosestream<<"Server: Handling peer change: "
5279                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
5280                                 <<std::endl;
5281
5282                 handlePeerChange(c);
5283         }
5284 }
5285
5286 void dedicated_server_loop(Server &server, bool &kill)
5287 {
5288         DSTACK(__FUNCTION_NAME);
5289
5290         verbosestream<<"dedicated_server_loop()"<<std::endl;
5291
5292         IntervalLimiter m_profiler_interval;
5293
5294         for(;;)
5295         {
5296                 float steplen = g_settings->getFloat("dedicated_server_step");
5297                 // This is kind of a hack but can be done like this
5298                 // because server.step() is very light
5299                 {
5300                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
5301                         sleep_ms((int)(steplen*1000.0));
5302                 }
5303                 server.step(steplen);
5304
5305                 if(server.getShutdownRequested() || kill)
5306                 {
5307                         infostream<<"Dedicated server quitting"<<std::endl;
5308 #if USE_CURL
5309                         if(g_settings->getBool("server_announce") == true)
5310                                 ServerList::sendAnnounce("delete");
5311 #endif
5312                         break;
5313                 }
5314
5315                 /*
5316                         Profiler
5317                 */
5318                 float profiler_print_interval =
5319                                 g_settings->getFloat("profiler_print_interval");
5320                 if(profiler_print_interval != 0)
5321                 {
5322                         if(m_profiler_interval.step(steplen, profiler_print_interval))
5323                         {
5324                                 infostream<<"Profiler:"<<std::endl;
5325                                 g_profiler->print(infostream);
5326                                 g_profiler->clear();
5327                         }
5328                 }
5329         }
5330 }
5331
5332