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