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