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