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