]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Weather backward compatibility
[dragonfireclient.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "clientserver.h"
25 #include "map.h"
26 #include "jmutexautolock.h"
27 #include "main.h"
28 #include "constants.h"
29 #include "voxel.h"
30 #include "config.h"
31 #include "filesys.h"
32 #include "mapblock.h"
33 #include "serverobject.h"
34 #include "settings.h"
35 #include "profiler.h"
36 #include "log.h"
37 #include "script/cpp_api/scriptapi.h"
38 #include "nodedef.h"
39 #include "itemdef.h"
40 #include "craftdef.h"
41 #include "emerge.h"
42 #include "mapgen.h"
43 #include "biome.h"
44 #include "content_mapnode.h"
45 #include "content_nodemeta.h"
46 #include "content_abm.h"
47 #include "content_sao.h"
48 #include "mods.h"
49 #include "sha1.h"
50 #include "base64.h"
51 #include "tool.h"
52 #include "sound.h" // dummySoundManager
53 #include "event_manager.h"
54 #include "hex.h"
55 #include "serverlist.h"
56 #include "util/string.h"
57 #include "util/pointedthing.h"
58 #include "util/mathconstants.h"
59 #include "rollback.h"
60 #include "util/serialize.h"
61 #include "defaultsettings.h"
62
63 void * ServerThread::Thread()
64 {
65         ThreadStarted();
66
67         log_register_thread("ServerThread");
68
69         DSTACK(__FUNCTION_NAME);
70
71         BEGIN_DEBUG_EXCEPTION_HANDLER
72
73         while(getRun())
74         {
75                 try{
76                         //TimeTaker timer("AsyncRunStep() + Receive()");
77
78                         {
79                                 //TimeTaker timer("AsyncRunStep()");
80                                 m_server->AsyncRunStep();
81                         }
82
83                         //infostream<<"Running m_server->Receive()"<<std::endl;
84                         m_server->Receive();
85                 }
86                 catch(con::NoIncomingDataException &e)
87                 {
88                 }
89                 catch(con::PeerNotFoundException &e)
90                 {
91                         infostream<<"Server: PeerNotFoundException"<<std::endl;
92                 }
93                 catch(con::ConnectionBindFailed &e)
94                 {
95                         m_server->setAsyncFatalError(e.what());
96                 }
97                 catch(LuaError &e)
98                 {
99                         m_server->setAsyncFatalError(e.what());
100                 }
101         }
102
103         END_DEBUG_EXCEPTION_HANDLER(errorstream)
104
105         return NULL;
106 }
107
108 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
109 {
110         if(pos_exists) *pos_exists = false;
111         switch(type){
112         case SSP_LOCAL:
113                 return v3f(0,0,0);
114         case SSP_POSITIONAL:
115                 if(pos_exists) *pos_exists = true;
116                 return pos;
117         case SSP_OBJECT: {
118                 if(object == 0)
119                         return v3f(0,0,0);
120                 ServerActiveObject *sao = env->getActiveObject(object);
121                 if(!sao)
122                         return v3f(0,0,0);
123                 if(pos_exists) *pos_exists = true;
124                 return sao->getBasePosition(); }
125         }
126         return v3f(0,0,0);
127 }
128
129 void RemoteClient::GetNextBlocks(Server *server, float dtime,
130                 std::vector<PrioritySortedBlockTransfer> &dest)
131 {
132         DSTACK(__FUNCTION_NAME);
133
134         /*u32 timer_result;
135         TimeTaker timer("RemoteClient::GetNextBlocks", &timer_result);*/
136
137         // Increment timers
138         m_nothing_to_send_pause_timer -= dtime;
139         m_nearest_unsent_reset_timer += dtime;
140
141         if(m_nothing_to_send_pause_timer >= 0)
142                 return;
143
144         Player *player = server->m_env->getPlayer(peer_id);
145         // This can happen sometimes; clients and players are not in perfect sync.
146         if(player == NULL)
147                 return;
148
149         // Won't send anything if already sending
150         if(m_blocks_sending.size() >= g_settings->getU16
151                         ("max_simultaneous_block_sends_per_client"))
152         {
153                 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
154                 return;
155         }
156
157         //TimeTaker timer("RemoteClient::GetNextBlocks");
158
159         v3f playerpos = player->getPosition();
160         v3f playerspeed = player->getSpeed();
161         v3f playerspeeddir(0,0,0);
162         if(playerspeed.getLength() > 1.0*BS)
163                 playerspeeddir = playerspeed / playerspeed.getLength();
164         // Predict to next block
165         v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
166
167         v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
168
169         v3s16 center = getNodeBlockPos(center_nodepos);
170
171         // Camera position and direction
172         v3f camera_pos = player->getEyePosition();
173         v3f camera_dir = v3f(0,0,1);
174         camera_dir.rotateYZBy(player->getPitch());
175         camera_dir.rotateXZBy(player->getYaw());
176
177         /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
178                         <<camera_dir.Z<<")"<<std::endl;*/
179
180         /*
181                 Get the starting value of the block finder radius.
182         */
183
184         if(m_last_center != center)
185         {
186                 m_nearest_unsent_d = 0;
187                 m_last_center = center;
188         }
189
190         /*infostream<<"m_nearest_unsent_reset_timer="
191                         <<m_nearest_unsent_reset_timer<<std::endl;*/
192
193         // Reset periodically to workaround for some bugs or stuff
194         if(m_nearest_unsent_reset_timer > 20.0)
195         {
196                 m_nearest_unsent_reset_timer = 0;
197                 m_nearest_unsent_d = 0;
198                 //infostream<<"Resetting m_nearest_unsent_d for "
199                 //              <<server->getPlayerName(peer_id)<<std::endl;
200         }
201
202         //s16 last_nearest_unsent_d = m_nearest_unsent_d;
203         s16 d_start = m_nearest_unsent_d;
204
205         //infostream<<"d_start="<<d_start<<std::endl;
206
207         u16 max_simul_sends_setting = g_settings->getU16
208                         ("max_simultaneous_block_sends_per_client");
209         u16 max_simul_sends_usually = max_simul_sends_setting;
210
211         /*
212                 Check the time from last addNode/removeNode.
213
214                 Decrease send rate if player is building stuff.
215         */
216         m_time_from_building += dtime;
217         if(m_time_from_building < g_settings->getFloat(
218                                 "full_block_send_enable_min_time_from_building"))
219         {
220                 max_simul_sends_usually
221                         = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
222         }
223
224         /*
225                 Number of blocks sending + number of blocks selected for sending
226         */
227         u32 num_blocks_selected = m_blocks_sending.size();
228
229         /*
230                 next time d will be continued from the d from which the nearest
231                 unsent block was found this time.
232
233                 This is because not necessarily any of the blocks found this
234                 time are actually sent.
235         */
236         s32 new_nearest_unsent_d = -1;
237
238         s16 d_max = g_settings->getS16("max_block_send_distance");
239         s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
240
241         // Don't loop very much at a time
242         s16 max_d_increment_at_time = 2;
243         if(d_max > d_start + max_d_increment_at_time)
244                 d_max = d_start + max_d_increment_at_time;
245         /*if(d_max_gen > d_start+2)
246                 d_max_gen = d_start+2;*/
247
248         //infostream<<"Starting from "<<d_start<<std::endl;
249
250         s32 nearest_emerged_d = -1;
251         s32 nearest_emergefull_d = -1;
252         s32 nearest_sent_d = -1;
253         bool queue_is_full = false;
254
255         s16 d;
256         for(d = d_start; d <= d_max; d++)
257         {
258                 /*errorstream<<"checking d="<<d<<" for "
259                                 <<server->getPlayerName(peer_id)<<std::endl;*/
260                 //infostream<<"RemoteClient::SendBlocks(): d="<<d<<std::endl;
261
262                 /*
263                         If m_nearest_unsent_d was changed by the EmergeThread
264                         (it can change it to 0 through SetBlockNotSent),
265                         update our d to it.
266                         Else update m_nearest_unsent_d
267                 */
268                 /*if(m_nearest_unsent_d != last_nearest_unsent_d)
269                 {
270                         d = m_nearest_unsent_d;
271                         last_nearest_unsent_d = m_nearest_unsent_d;
272                 }*/
273
274                 /*
275                         Get the border/face dot coordinates of a "d-radiused"
276                         box
277                 */
278                 std::list<v3s16> list;
279                 getFacePositions(list, d);
280
281                 std::list<v3s16>::iterator li;
282                 for(li=list.begin(); li!=list.end(); ++li)
283                 {
284                         v3s16 p = *li + center;
285
286                         /*
287                                 Send throttling
288                                 - Don't allow too many simultaneous transfers
289                                 - EXCEPT when the blocks are very close
290
291                                 Also, don't send blocks that are already flying.
292                         */
293
294                         // Start with the usual maximum
295                         u16 max_simul_dynamic = max_simul_sends_usually;
296
297                         // If block is very close, allow full maximum
298                         if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
299                                 max_simul_dynamic = max_simul_sends_setting;
300
301                         // Don't select too many blocks for sending
302                         if(num_blocks_selected >= max_simul_dynamic)
303                         {
304                                 queue_is_full = true;
305                                 goto queue_full_break;
306                         }
307
308                         // Don't send blocks that are currently being transferred
309                         if(m_blocks_sending.find(p) != m_blocks_sending.end())
310                                 continue;
311
312                         /*
313                                 Do not go over-limit
314                         */
315                         if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
316                         || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
317                         || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
318                         || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
319                         || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
320                         || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
321                                 continue;
322
323                         // If this is true, inexistent block will be made from scratch
324                         bool generate = d <= d_max_gen;
325
326                         {
327                                 /*// Limit the generating area vertically to 2/3
328                                 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
329                                         generate = false;*/
330
331                                 // Limit the send area vertically to 1/2
332                                 if(abs(p.Y - center.Y) > d_max / 2)
333                                         continue;
334                         }
335
336 #if 0
337                         /*
338                                 If block is far away, don't generate it unless it is
339                                 near ground level.
340                         */
341                         if(d >= 4)
342                         {
343         #if 1
344                                 // Block center y in nodes
345                                 f32 y = (f32)(p.Y * MAP_BLOCKSIZE + MAP_BLOCKSIZE/2);
346                                 // Don't generate if it's very high or very low
347                                 if(y < -64 || y > 64)
348                                         generate = false;
349         #endif
350         #if 0
351                                 v2s16 p2d_nodes_center(
352                                         MAP_BLOCKSIZE*p.X,
353                                         MAP_BLOCKSIZE*p.Z);
354
355                                 // Get ground height in nodes
356                                 s16 gh = server->m_env->getServerMap().findGroundLevel(
357                                                 p2d_nodes_center);
358
359                                 // If differs a lot, don't generate
360                                 if(fabs(gh - y) > MAP_BLOCKSIZE*2)
361                                         generate = false;
362                                         // Actually, don't even send it
363                                         //continue;
364         #endif
365                         }
366 #endif
367
368                         //infostream<<"d="<<d<<std::endl;
369 #if 1
370                         /*
371                                 Don't generate or send if not in sight
372                                 FIXME This only works if the client uses a small enough
373                                 FOV setting. The default of 72 degrees is fine.
374                         */
375
376                         float camera_fov = (72.0*M_PI/180) * 4./3.;
377                         if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
378                         {
379                                 continue;
380                         }
381 #endif
382                         /*
383                                 Don't send already sent blocks
384                         */
385                         {
386                                 if(m_blocks_sent.find(p) != m_blocks_sent.end())
387                                 {
388                                         continue;
389                                 }
390                         }
391
392                         /*
393                                 Check if map has this block
394                         */
395                         MapBlock *block = server->m_env->getMap().getBlockNoCreateNoEx(p);
396
397                         bool surely_not_found_on_disk = false;
398                         bool block_is_invalid = false;
399                         if(block != NULL)
400                         {
401                                 // Reset usage timer, this block will be of use in the future.
402                                 block->resetUsageTimer();
403
404                                 // Block is dummy if data doesn't exist.
405                                 // It means it has been not found from disk and not generated
406                                 if(block->isDummy())
407                                 {
408                                         surely_not_found_on_disk = true;
409                                 }
410
411                                 // Block is valid if lighting is up-to-date and data exists
412                                 if(block->isValid() == false)
413                                 {
414                                         block_is_invalid = true;
415                                 }
416
417                                 /*if(block->isFullyGenerated() == false)
418                                 {
419                                         block_is_invalid = true;
420                                 }*/
421
422 #if 0
423                                 v2s16 p2d(p.X, p.Z);
424                                 ServerMap *map = (ServerMap*)(&server->m_env->getMap());
425                                 v2s16 chunkpos = map->sector_to_chunk(p2d);
426                                 if(map->chunkNonVolatile(chunkpos) == false)
427                                         block_is_invalid = true;
428 #endif
429                                 if(block->isGenerated() == false)
430                                         block_is_invalid = true;
431 #if 1
432                                 /*
433                                         If block is not close, don't send it unless it is near
434                                         ground level.
435
436                                         Block is near ground level if night-time mesh
437                                         differs from day-time mesh.
438                                 */
439                                 if(d >= 4)
440                                 {
441                                         if(block->getDayNightDiff() == false)
442                                                 continue;
443                                 }
444 #endif
445                         }
446
447                         /*
448                                 If block has been marked to not exist on disk (dummy)
449                                 and generating new ones is not wanted, skip block.
450                         */
451                         if(generate == false && surely_not_found_on_disk == true)
452                         {
453                                 // get next one.
454                                 continue;
455                         }
456
457                         /*
458                                 Add inexistent block to emerge queue.
459                         */
460                         if(block == NULL || surely_not_found_on_disk || block_is_invalid)
461                         {
462                         /*      //TODO: Get value from somewhere
463                                 // Allow only one block in emerge queue
464                                 //if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
465                                 // Allow two blocks in queue per client
466                                 //if(server->m_emerge_queue.peerItemCount(peer_id) < 2)
467                                 u32 max_emerge = 5;
468                                 // Make it more responsive when needing to generate stuff
469                                 if(surely_not_found_on_disk)
470                                         max_emerge = 1;
471                                 if(server->m_emerge_queue.peerItemCount(peer_id) < max_emerge)
472                                 {
473                                         //infostream<<"Adding block to emerge queue"<<std::endl;
474
475                                         // Add it to the emerge queue and trigger the thread
476
477                                         u8 flags = 0;
478                                         if(generate == false)
479                                                 flags |= BLOCK_EMERGE_FLAG_FROMDISK;
480
481                                         server->m_emerge_queue.addBlock(peer_id, p, flags);
482                                         server->m_emergethread.trigger();
483
484                                         if(nearest_emerged_d == -1)
485                                                 nearest_emerged_d = d;
486                                 } else {
487                                         if(nearest_emergefull_d == -1)
488                                                 nearest_emergefull_d = d;
489                                         goto queue_full_break;
490                                 }
491                         */
492
493                                 if (server->m_emerge->enqueueBlockEmerge(peer_id, p, generate)) {
494                                         if (nearest_emerged_d == -1)
495                                                 nearest_emerged_d = d;
496                                 } else {
497                                         if (nearest_emergefull_d == -1)
498                                                 nearest_emergefull_d = d;
499                                         goto queue_full_break;
500                                 }
501                                 
502                                 // get next one.
503                                 continue;
504                         }
505
506                         if(nearest_sent_d == -1)
507                                 nearest_sent_d = d;
508
509                         /*
510                                 Add block to send queue
511                         */
512
513                         /*errorstream<<"sending from d="<<d<<" to "
514                                         <<server->getPlayerName(peer_id)<<std::endl;*/
515
516                         PrioritySortedBlockTransfer q((float)d, p, peer_id);
517
518                         dest.push_back(q);
519
520                         num_blocks_selected += 1;
521                 }
522         }
523 queue_full_break:
524
525         //infostream<<"Stopped at "<<d<<std::endl;
526
527         // If nothing was found for sending and nothing was queued for
528         // emerging, continue next time browsing from here
529         if(nearest_emerged_d != -1){
530                 new_nearest_unsent_d = nearest_emerged_d;
531         } else if(nearest_emergefull_d != -1){
532                 new_nearest_unsent_d = nearest_emergefull_d;
533         } else {
534                 if(d > g_settings->getS16("max_block_send_distance")){
535                         new_nearest_unsent_d = 0;
536                         m_nothing_to_send_pause_timer = 2.0;
537                         /*infostream<<"GetNextBlocks(): d wrapped around for "
538                                         <<server->getPlayerName(peer_id)
539                                         <<"; setting to 0 and pausing"<<std::endl;*/
540                 } else {
541                         if(nearest_sent_d != -1)
542                                 new_nearest_unsent_d = nearest_sent_d;
543                         else
544                                 new_nearest_unsent_d = d;
545                 }
546         }
547
548         if(new_nearest_unsent_d != -1)
549                 m_nearest_unsent_d = new_nearest_unsent_d;
550
551         /*timer_result = timer.stop(true);
552         if(timer_result != 0)
553                 infostream<<"GetNextBlocks timeout: "<<timer_result<<" (!=0)"<<std::endl;*/
554 }
555
556 void RemoteClient::GotBlock(v3s16 p)
557 {
558         if(m_blocks_sending.find(p) != m_blocks_sending.end())
559                 m_blocks_sending.erase(p);
560         else
561         {
562                 /*infostream<<"RemoteClient::GotBlock(): Didn't find in"
563                                 " m_blocks_sending"<<std::endl;*/
564                 m_excess_gotblocks++;
565         }
566         m_blocks_sent.insert(p);
567 }
568
569 void RemoteClient::SentBlock(v3s16 p)
570 {
571         if(m_blocks_sending.find(p) == m_blocks_sending.end())
572                 m_blocks_sending[p] = 0.0;
573         else
574                 infostream<<"RemoteClient::SentBlock(): Sent block"
575                                 " already in m_blocks_sending"<<std::endl;
576 }
577
578 void RemoteClient::SetBlockNotSent(v3s16 p)
579 {
580         m_nearest_unsent_d = 0;
581
582         if(m_blocks_sending.find(p) != m_blocks_sending.end())
583                 m_blocks_sending.erase(p);
584         if(m_blocks_sent.find(p) != m_blocks_sent.end())
585                 m_blocks_sent.erase(p);
586 }
587
588 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
589 {
590         m_nearest_unsent_d = 0;
591
592         for(std::map<v3s16, MapBlock*>::iterator
593                         i = blocks.begin();
594                         i != blocks.end(); ++i)
595         {
596                 v3s16 p = i->first;
597
598                 if(m_blocks_sending.find(p) != m_blocks_sending.end())
599                         m_blocks_sending.erase(p);
600                 if(m_blocks_sent.find(p) != m_blocks_sent.end())
601                         m_blocks_sent.erase(p);
602         }
603 }
604
605 /*
606         PlayerInfo
607 */
608
609 PlayerInfo::PlayerInfo()
610 {
611         name[0] = 0;
612         avg_rtt = 0;
613 }
614
615 void PlayerInfo::PrintLine(std::ostream *s)
616 {
617         (*s)<<id<<": ";
618         (*s)<<"\""<<name<<"\" ("
619                         <<(position.X/10)<<","<<(position.Y/10)
620                         <<","<<(position.Z/10)<<") ";
621         address.print(s);
622         (*s)<<" avg_rtt="<<avg_rtt;
623         (*s)<<std::endl;
624 }
625
626 /*
627         Server
628 */
629
630 Server::Server(
631                 const std::string &path_world,
632                 const std::string &path_config,
633                 const SubgameSpec &gamespec,
634                 bool simple_singleplayer_mode
635         ):
636         m_path_world(path_world),
637         m_path_config(path_config),
638         m_gamespec(gamespec),
639         m_simple_singleplayer_mode(simple_singleplayer_mode),
640         m_async_fatal_error(""),
641         m_env(NULL),
642         m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT,
643               g_settings->getBool("enable_ipv6") && g_settings->getBool("ipv6_server"), this),
644         m_banmanager(path_world+DIR_DELIM+"ipban.txt"),
645         m_rollback(NULL),
646         m_rollback_sink_enabled(true),
647         m_enable_rollback_recording(false),
648         m_emerge(NULL),
649         m_script(NULL),
650         m_itemdef(createItemDefManager()),
651         m_nodedef(createNodeDefManager()),
652         m_craftdef(createCraftDefManager()),
653         m_event(new EventManager()),
654         m_thread(this),
655         m_time_of_day_send_timer(0),
656         m_uptime(0),
657         m_shutdown_requested(false),
658         m_ignore_map_edit_events(false),
659         m_ignore_map_edit_events_peer_id(0)
660 {
661         m_liquid_transform_timer = 0.0;
662         m_liquid_transform_every = 1.0;
663         m_print_info_timer = 0.0;
664         m_masterserver_timer = 0.0;
665         m_objectdata_timer = 0.0;
666         m_emergethread_trigger_timer = 0.0;
667         m_savemap_timer = 0.0;
668         m_clients_number = 0;
669
670         m_env_mutex.Init();
671         m_con_mutex.Init();
672         m_step_dtime_mutex.Init();
673         m_step_dtime = 0.0;
674
675         if(path_world == "")
676                 throw ServerError("Supplied empty world path");
677
678         if(!gamespec.isValid())
679                 throw ServerError("Supplied invalid gamespec");
680
681         infostream<<"Server created for gameid \""<<m_gamespec.id<<"\"";
682         if(m_simple_singleplayer_mode)
683                 infostream<<" in simple singleplayer mode"<<std::endl;
684         else
685                 infostream<<std::endl;
686         infostream<<"- world:  "<<m_path_world<<std::endl;
687         infostream<<"- config: "<<m_path_config<<std::endl;
688         infostream<<"- game:   "<<m_gamespec.path<<std::endl;
689
690         // Initialize default settings and override defaults with those provided
691         // by the game
692         set_default_settings(g_settings);
693         Settings gamedefaults;
694         getGameMinetestConfig(gamespec.path, gamedefaults);
695         override_default_settings(g_settings, &gamedefaults);
696         
697         // Create emerge manager
698         m_emerge = new EmergeManager(this);
699         
700         // Create rollback manager
701         std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt";
702         m_rollback = createRollbackManager(rollback_path, this);
703
704         // Create world if it doesn't exist
705         if(!initializeWorld(m_path_world, m_gamespec.id))
706                 throw ServerError("Failed to initialize world");
707
708         ModConfiguration modconf(m_path_world);
709         m_mods = modconf.getMods();
710         std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
711         // complain about mods with unsatisfied dependencies
712         if(!modconf.isConsistent())     
713         {
714                 for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
715                         it != unsatisfied_mods.end(); ++it)
716                 {
717                         ModSpec mod = *it;
718                         errorstream << "mod \"" << mod.name << "\" has unsatisfied dependencies: ";
719                         for(std::set<std::string>::iterator dep_it = mod.unsatisfied_depends.begin();
720                                 dep_it != mod.unsatisfied_depends.end(); ++dep_it)
721                                 errorstream << " \"" << *dep_it << "\"";
722                         errorstream << std::endl;
723                 }
724         }
725
726         Settings worldmt_settings;
727         std::string worldmt = m_path_world + DIR_DELIM + "world.mt";
728         worldmt_settings.readConfigFile(worldmt.c_str());
729         std::vector<std::string> names = worldmt_settings.getNames();
730         std::set<std::string> load_mod_names;
731         for(std::vector<std::string>::iterator it = names.begin(); 
732                 it != names.end(); ++it)
733         {       
734                 std::string name = *it;  
735                 if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name))
736                         load_mod_names.insert(name.substr(9));
737         }
738         // complain about mods declared to be loaded, but not found
739         for(std::vector<ModSpec>::iterator it = m_mods.begin();
740                         it != m_mods.end(); ++it)
741                 load_mod_names.erase((*it).name);
742         for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
743                         it != unsatisfied_mods.end(); ++it)
744                 load_mod_names.erase((*it).name);
745         if(!load_mod_names.empty())
746         {               
747                 errorstream << "The following mods could not be found:";
748                 for(std::set<std::string>::iterator it = load_mod_names.begin();
749                         it != load_mod_names.end(); ++it)
750                         errorstream << " \"" << (*it) << "\"";
751                 errorstream << std::endl;
752         }
753
754         // Path to builtin.lua
755         std::string builtinpath = getBuiltinLuaPath() + DIR_DELIM + "builtin.lua";
756
757         // Lock environment
758         JMutexAutoLock envlock(m_env_mutex);
759         JMutexAutoLock conlock(m_con_mutex);
760
761         // Initialize scripting
762
763         infostream<<"Server: Initializing Lua"<<std::endl;
764
765         m_script = new ScriptApi(this);
766
767
768         // Load and run builtin.lua
769         infostream<<"Server: Loading builtin.lua [\""
770                         <<builtinpath<<"\"]"<<std::endl;
771         bool success = m_script->loadMod(builtinpath, "__builtin");
772         if(!success){
773                 errorstream<<"Server: Failed to load and run "
774                                 <<builtinpath<<std::endl;
775                 throw ModError("Failed to load and run "+builtinpath);
776         }
777         // Print 'em
778         infostream<<"Server: Loading mods: ";
779         for(std::vector<ModSpec>::iterator i = m_mods.begin();
780                         i != m_mods.end(); i++){
781                 const ModSpec &mod = *i;
782                 infostream<<mod.name<<" ";
783         }
784         infostream<<std::endl;
785         // Load and run "mod" scripts
786         for(std::vector<ModSpec>::iterator i = m_mods.begin();
787                         i != m_mods.end(); i++){
788                 const ModSpec &mod = *i;
789                 std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
790                 infostream<<"  ["<<padStringRight(mod.name, 12)<<"] [\""
791                                 <<scriptpath<<"\"]"<<std::endl;
792                 bool success = m_script->loadMod(scriptpath, mod.name);
793                 if(!success){
794                         errorstream<<"Server: Failed to load and run "
795                                         <<scriptpath<<std::endl;
796                         throw ModError("Failed to load and run "+scriptpath);
797                 }
798         }
799
800         // Read Textures and calculate sha1 sums
801         fillMediaCache();
802
803         // Apply item aliases in the node definition manager
804         m_nodedef->updateAliases(m_itemdef);
805
806         // Initialize Environment
807         ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
808         m_env = new ServerEnvironment(servermap, m_script, this, this);
809         
810         // 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(!isSingleplayer() && (!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         std::string addr_s;
1749         try{
1750                 Address address = m_con.GetPeerAddress(peer_id);
1751                 addr_s = address.serializeString();
1752
1753                 // drop player if is ip is banned
1754                 if(m_banmanager.isIpBanned(addr_s)){
1755                         infostream<<"Server: A banned client tried to connect from "
1756                                         <<addr_s<<"; banned name was "
1757                                         <<m_banmanager.getBanName(addr_s)<<std::endl;
1758                         // This actually doesn't seem to transfer to the client
1759                         SendAccessDenied(m_con, peer_id,
1760                                         L"Your ip is banned. Banned name was "
1761                                         +narrow_to_wide(m_banmanager.getBanName(addr_s)));
1762                         m_con.DeletePeer(peer_id);
1763                         return;
1764                 }
1765         }
1766         catch(con::PeerNotFoundException &e)
1767         {
1768                 infostream<<"Server::ProcessData(): Cancelling: peer "
1769                                 <<peer_id<<" not found"<<std::endl;
1770                 return;
1771         }
1772
1773         u8 peer_ser_ver = getClient(peer_id)->serialization_version;
1774
1775         try
1776         {
1777
1778         if(datasize < 2)
1779                 return;
1780
1781         ToServerCommand command = (ToServerCommand)readU16(&data[0]);
1782
1783         if(command == TOSERVER_INIT)
1784         {
1785                 // [0] u16 TOSERVER_INIT
1786                 // [2] u8 SER_FMT_VER_HIGHEST_READ
1787                 // [3] u8[20] player_name
1788                 // [23] u8[28] password <--- can be sent without this, from old versions
1789
1790                 if(datasize < 2+1+PLAYERNAME_SIZE)
1791                         return;
1792
1793                 verbosestream<<"Server: Got TOSERVER_INIT from "
1794                                 <<peer_id<<std::endl;
1795
1796                 // First byte after command is maximum supported
1797                 // serialization version
1798                 u8 client_max = data[2];
1799                 u8 our_max = SER_FMT_VER_HIGHEST_READ;
1800                 // Use the highest version supported by both
1801                 u8 deployed = std::min(client_max, our_max);
1802                 // If it's lower than the lowest supported, give up.
1803                 if(deployed < SER_FMT_VER_LOWEST)
1804                         deployed = SER_FMT_VER_INVALID;
1805
1806                 //peer->serialization_version = deployed;
1807                 getClient(peer_id)->pending_serialization_version = deployed;
1808
1809                 if(deployed == SER_FMT_VER_INVALID)
1810                 {
1811                         actionstream<<"Server: A mismatched client tried to connect from "
1812                                         <<addr_s<<std::endl;
1813                         infostream<<"Server: Cannot negotiate "
1814                                         "serialization version with peer "
1815                                         <<peer_id<<std::endl;
1816                         SendAccessDenied(m_con, peer_id, std::wstring(
1817                                         L"Your client's version is not supported.\n"
1818                                         L"Server version is ")
1819                                         + narrow_to_wide(VERSION_STRING) + L"."
1820                         );
1821                         return;
1822                 }
1823
1824                 /*
1825                         Read and check network protocol version
1826                 */
1827
1828                 u16 min_net_proto_version = 0;
1829                 if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2)
1830                         min_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
1831
1832                 // Use same version as minimum and maximum if maximum version field
1833                 // doesn't exist (backwards compatibility)
1834                 u16 max_net_proto_version = min_net_proto_version;
1835                 if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2)
1836                         max_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2]);
1837
1838                 // Start with client's maximum version
1839                 u16 net_proto_version = max_net_proto_version;
1840
1841                 // Figure out a working version if it is possible at all
1842                 if(max_net_proto_version >= SERVER_PROTOCOL_VERSION_MIN ||
1843                                 min_net_proto_version <= SERVER_PROTOCOL_VERSION_MAX)
1844                 {
1845                         // If maximum is larger than our maximum, go with our maximum
1846                         if(max_net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
1847                                 net_proto_version = SERVER_PROTOCOL_VERSION_MAX;
1848                         // Else go with client's maximum
1849                         else
1850                                 net_proto_version = max_net_proto_version;
1851                 }
1852
1853                 verbosestream<<"Server: "<<peer_id<<" Protocol version: min: "
1854                                 <<min_net_proto_version<<", max: "<<max_net_proto_version
1855                                 <<", chosen: "<<net_proto_version<<std::endl;
1856
1857                 getClient(peer_id)->net_proto_version = net_proto_version;
1858
1859                 if(net_proto_version < SERVER_PROTOCOL_VERSION_MIN ||
1860                                 net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
1861                 {
1862                         actionstream<<"Server: A mismatched client tried to connect from "<<addr_s
1863                                         <<std::endl;
1864                         SendAccessDenied(m_con, peer_id, std::wstring(
1865                                         L"Your client's version is not supported.\n"
1866                                         L"Server version is ")
1867                                         + narrow_to_wide(VERSION_STRING) + L",\n"
1868                                         + L"server's PROTOCOL_VERSION is "
1869                                         + narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MIN))
1870                                         + L"..."
1871                                         + narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MAX))
1872                                         + L", client's PROTOCOL_VERSION is "
1873                                         + narrow_to_wide(itos(min_net_proto_version))
1874                                         + L"..."
1875                                         + narrow_to_wide(itos(max_net_proto_version))
1876                         );
1877                         return;
1878                 }
1879
1880                 if(g_settings->getBool("strict_protocol_version_checking"))
1881                 {
1882                         if(net_proto_version != LATEST_PROTOCOL_VERSION)
1883                         {
1884                                 actionstream<<"Server: A mismatched (strict) client tried to "
1885                                                 <<"connect from "<<addr_s<<std::endl;
1886                                 SendAccessDenied(m_con, peer_id, std::wstring(
1887                                                 L"Your client's version is not supported.\n"
1888                                                 L"Server version is ")
1889                                                 + narrow_to_wide(VERSION_STRING) + L",\n"
1890                                                 + L"server's PROTOCOL_VERSION (strict) is "
1891                                                 + narrow_to_wide(itos(LATEST_PROTOCOL_VERSION))
1892                                                 + L", client's PROTOCOL_VERSION is "
1893                                                 + narrow_to_wide(itos(min_net_proto_version))
1894                                                 + L"..."
1895                                                 + narrow_to_wide(itos(max_net_proto_version))
1896                                 );
1897                                 return;
1898                         }
1899                 }
1900
1901                 /*
1902                         Set up player
1903                 */
1904
1905                 // Get player name
1906                 char playername[PLAYERNAME_SIZE];
1907                 for(u32 i=0; i<PLAYERNAME_SIZE-1; i++)
1908                 {
1909                         playername[i] = data[3+i];
1910                 }
1911                 playername[PLAYERNAME_SIZE-1] = 0;
1912
1913                 if(playername[0]=='\0')
1914                 {
1915                         actionstream<<"Server: Player with an empty name "
1916                                         <<"tried to connect from "<<addr_s<<std::endl;
1917                         SendAccessDenied(m_con, peer_id,
1918                                         L"Empty name");
1919                         return;
1920                 }
1921
1922                 if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false)
1923                 {
1924                         actionstream<<"Server: Player with an invalid name "
1925                                         <<"tried to connect from "<<addr_s<<std::endl;
1926                         SendAccessDenied(m_con, peer_id,
1927                                         L"Name contains unallowed characters");
1928                         return;
1929                 }
1930
1931                 if(!isSingleplayer() && strcasecmp(playername, "singleplayer") == 0)
1932                 {
1933                         actionstream<<"Server: Player with an invalid name "
1934                                         <<"tried to connect from "<<addr_s<<std::endl;
1935                         SendAccessDenied(m_con, peer_id,
1936                                         L"Name is not allowed");
1937                         return;
1938                 }
1939
1940                 infostream<<"Server: New connection: \""<<playername<<"\" from "
1941                                 <<m_con.GetPeerAddress(peer_id).serializeString()<<std::endl;
1942
1943                 // Get password
1944                 char given_password[PASSWORD_SIZE];
1945                 if(datasize < 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE)
1946                 {
1947                         // old version - assume blank password
1948                         given_password[0] = 0;
1949                 }
1950                 else
1951                 {
1952                         for(u32 i=0; i<PASSWORD_SIZE-1; i++)
1953                         {
1954                                 given_password[i] = data[23+i];
1955                         }
1956                         given_password[PASSWORD_SIZE-1] = 0;
1957                 }
1958
1959                 if(!base64_is_valid(given_password)){
1960                         infostream<<"Server: "<<playername
1961                                         <<" supplied invalid password hash"<<std::endl;
1962                         SendAccessDenied(m_con, peer_id, L"Invalid password hash");
1963                         return;
1964                 }
1965
1966                 std::string checkpwd; // Password hash to check against
1967                 bool has_auth = m_script->getAuth(playername, &checkpwd, NULL);
1968
1969                 // If no authentication info exists for user, create it
1970                 if(!has_auth){
1971                         if(!isSingleplayer() &&
1972                                         g_settings->getBool("disallow_empty_password") &&
1973                                         std::string(given_password) == ""){
1974                                 SendAccessDenied(m_con, peer_id, L"Empty passwords are "
1975                                                 L"disallowed. Set a password and try again.");
1976                                 return;
1977                         }
1978                         std::wstring raw_default_password =
1979                                 narrow_to_wide(g_settings->get("default_password"));
1980                         std::string initial_password =
1981                                 translatePassword(playername, raw_default_password);
1982
1983                         // If default_password is empty, allow any initial password
1984                         if (raw_default_password.length() == 0)
1985                                 initial_password = given_password;
1986
1987                         m_script->createAuth(playername, initial_password);
1988                 }
1989
1990                 has_auth = m_script->getAuth(playername, &checkpwd, NULL);
1991
1992                 if(!has_auth){
1993                         SendAccessDenied(m_con, peer_id, L"Not allowed to login");
1994                         return;
1995                 }
1996
1997                 if(given_password != checkpwd){
1998                         infostream<<"Server: peer_id="<<peer_id
1999                                         <<": supplied invalid password for "
2000                                         <<playername<<std::endl;
2001                         SendAccessDenied(m_con, peer_id, L"Invalid password");
2002                         return;
2003                 }
2004
2005                 // Do not allow multiple players in simple singleplayer mode.
2006                 // This isn't a perfect way to do it, but will suffice for now.
2007                 if(m_simple_singleplayer_mode && m_clients.size() > 1){
2008                         infostream<<"Server: Not allowing another client to connect in"
2009                                         <<" simple singleplayer mode"<<std::endl;
2010                         SendAccessDenied(m_con, peer_id,
2011                                         L"Running in simple singleplayer mode.");
2012                         return;
2013                 }
2014
2015                 // Enforce user limit.
2016                 // Don't enforce for users that have some admin right
2017                 if(m_clients.size() >= g_settings->getU16("max_users") &&
2018                                 !checkPriv(playername, "server") &&
2019                                 !checkPriv(playername, "ban") &&
2020                                 !checkPriv(playername, "privs") &&
2021                                 !checkPriv(playername, "password") &&
2022                                 playername != g_settings->get("name"))
2023                 {
2024                         actionstream<<"Server: "<<playername<<" tried to join, but there"
2025                                         <<" are already max_users="
2026                                         <<g_settings->getU16("max_users")<<" players."<<std::endl;
2027                         SendAccessDenied(m_con, peer_id, L"Too many users.");
2028                         return;
2029                 }
2030
2031                 // Get player
2032                 PlayerSAO *playersao = emergePlayer(playername, peer_id);
2033
2034                 // If failed, cancel
2035                 if(playersao == NULL)
2036                 {
2037                         errorstream<<"Server: peer_id="<<peer_id
2038                                         <<": failed to emerge player"<<std::endl;
2039                         return;
2040                 }
2041
2042                 /*
2043                         Answer with a TOCLIENT_INIT
2044                 */
2045                 {
2046                         SharedBuffer<u8> reply(2+1+6+8+4);
2047                         writeU16(&reply[0], TOCLIENT_INIT);
2048                         writeU8(&reply[2], deployed);
2049                         writeV3S16(&reply[2+1], floatToInt(playersao->getPlayer()->getPosition()+v3f(0,BS/2,0), BS));
2050                         writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
2051                         writeF1000(&reply[2+1+6+8], g_settings->getFloat("dedicated_server_step"));
2052
2053                         // Send as reliable
2054                         m_con.Send(peer_id, 0, reply, true);
2055                 }
2056
2057                 /*
2058                         Send complete position information
2059                 */
2060                 SendMovePlayer(peer_id);
2061
2062                 return;
2063         }
2064
2065         if(command == TOSERVER_INIT2)
2066         {
2067                 verbosestream<<"Server: Got TOSERVER_INIT2 from "
2068                                 <<peer_id<<std::endl;
2069
2070                 Player *player = m_env->getPlayer(peer_id);
2071                 if(!player){
2072                         verbosestream<<"Server: TOSERVER_INIT2: "
2073                                         <<"Player not found; ignoring."<<std::endl;
2074                         return;
2075                 }
2076
2077                 RemoteClient *client = getClient(peer_id);
2078                 client->serialization_version =
2079                                 getClient(peer_id)->pending_serialization_version;
2080
2081                 /*
2082                         Send some initialization data
2083                 */
2084
2085                 infostream<<"Server: Sending content to "
2086                                 <<getPlayerName(peer_id)<<std::endl;
2087
2088                 // Send player movement settings
2089                 SendMovement(m_con, peer_id);
2090
2091                 // Send item definitions
2092                 SendItemDef(m_con, peer_id, m_itemdef, client->net_proto_version);
2093
2094                 // Send node definitions
2095                 SendNodeDef(m_con, peer_id, m_nodedef, client->net_proto_version);
2096
2097                 // Send media announcement
2098                 sendMediaAnnouncement(peer_id);
2099
2100                 // Send privileges
2101                 SendPlayerPrivileges(peer_id);
2102
2103                 // Send inventory formspec
2104                 SendPlayerInventoryFormspec(peer_id);
2105
2106                 // Send inventory
2107                 UpdateCrafting(peer_id);
2108                 SendInventory(peer_id);
2109
2110                 // Send HP
2111                 if(g_settings->getBool("enable_damage"))
2112                         SendPlayerHP(peer_id);
2113
2114                 // Send Breath
2115                 SendPlayerBreath(peer_id);
2116
2117                 // Send detached inventories
2118                 sendDetachedInventories(peer_id);
2119
2120                 // Show death screen if necessary
2121                 if(player->hp == 0)
2122                         SendDeathscreen(m_con, peer_id, false, v3f(0,0,0));
2123
2124                 // Send time of day
2125                 {
2126                         SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
2127                                         m_env->getTimeOfDay(), g_settings->getFloat("time_speed"));
2128                         m_con.Send(peer_id, 0, data, true);
2129                 }
2130
2131                 // Note things in chat if not in simple singleplayer mode
2132                 if(!m_simple_singleplayer_mode)
2133                 {
2134                         // Send information about server to player in chat
2135                         SendChatMessage(peer_id, getStatusString());
2136
2137                         // Send information about joining in chat
2138                         {
2139                                 std::wstring name = L"unknown";
2140                                 Player *player = m_env->getPlayer(peer_id);
2141                                 if(player != NULL)
2142                                         name = narrow_to_wide(player->getName());
2143
2144                                 std::wstring message;
2145                                 message += L"*** ";
2146                                 message += name;
2147                                 message += L" joined the game.";
2148                                 BroadcastChatMessage(message);
2149                         }
2150                 }
2151
2152                 // Warnings about protocol version can be issued here
2153                 if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION)
2154                 {
2155                         SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT'S "
2156                                         L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!");
2157                 }
2158
2159                 /*
2160                         Print out action
2161                 */
2162                 {
2163                         std::ostringstream os(std::ios_base::binary);
2164                         for(std::map<u16, RemoteClient*>::iterator
2165                                 i = m_clients.begin();
2166                                 i != m_clients.end(); ++i)
2167                         {
2168                                 RemoteClient *client = i->second;
2169                                 assert(client->peer_id == i->first);
2170                                 if(client->serialization_version == SER_FMT_VER_INVALID)
2171                                         continue;
2172                                 // Get player
2173                                 Player *player = m_env->getPlayer(client->peer_id);
2174                                 if(!player)
2175                                         continue;
2176                                 // Get name of player
2177                                 os<<player->getName()<<" ";
2178                         }
2179
2180                         actionstream<<player->getName()<<" ["<<addr_s<<"] "<<"joins game. List of players: "
2181                                         <<os.str()<<std::endl;
2182                 }
2183
2184                 return;
2185         }
2186
2187         if(peer_ser_ver == SER_FMT_VER_INVALID)
2188         {
2189                 infostream<<"Server::ProcessData(): Cancelling: Peer"
2190                                 " serialization format invalid or not initialized."
2191                                 " Skipping incoming command="<<command<<std::endl;
2192                 return;
2193         }
2194
2195         Player *player = m_env->getPlayer(peer_id);
2196         if(player == NULL){
2197                 infostream<<"Server::ProcessData(): Cancelling: "
2198                                 "No player for peer_id="<<peer_id
2199                                 <<std::endl;
2200                 return;
2201         }
2202
2203         PlayerSAO *playersao = player->getPlayerSAO();
2204         if(playersao == NULL){
2205                 infostream<<"Server::ProcessData(): Cancelling: "
2206                                 "No player object for peer_id="<<peer_id
2207                                 <<std::endl;
2208                 return;
2209         }
2210
2211         if(command == TOSERVER_PLAYERPOS)
2212         {
2213                 if(datasize < 2+12+12+4+4)
2214                         return;
2215
2216                 u32 start = 0;
2217                 v3s32 ps = readV3S32(&data[start+2]);
2218                 v3s32 ss = readV3S32(&data[start+2+12]);
2219                 f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0;
2220                 f32 yaw = (f32)readS32(&data[2+12+12+4]) / 100.0;
2221                 u32 keyPressed = 0;
2222                 if(datasize >= 2+12+12+4+4+4)
2223                         keyPressed = (u32)readU32(&data[2+12+12+4+4]);
2224                 v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.);
2225                 v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.);
2226                 pitch = wrapDegrees(pitch);
2227                 yaw = wrapDegrees(yaw);
2228
2229                 player->setPosition(position);
2230                 player->setSpeed(speed);
2231                 player->setPitch(pitch);
2232                 player->setYaw(yaw);
2233                 player->keyPressed=keyPressed;
2234                 player->control.up = (bool)(keyPressed&1);
2235                 player->control.down = (bool)(keyPressed&2);
2236                 player->control.left = (bool)(keyPressed&4);
2237                 player->control.right = (bool)(keyPressed&8);
2238                 player->control.jump = (bool)(keyPressed&16);
2239                 player->control.aux1 = (bool)(keyPressed&32);
2240                 player->control.sneak = (bool)(keyPressed&64);
2241                 player->control.LMB = (bool)(keyPressed&128);
2242                 player->control.RMB = (bool)(keyPressed&256);
2243
2244                 /*infostream<<"Server::ProcessData(): Moved player "<<peer_id<<" to "
2245                                 <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
2246                                 <<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
2247         }
2248         else if(command == TOSERVER_GOTBLOCKS)
2249         {
2250                 if(datasize < 2+1)
2251                         return;
2252
2253                 /*
2254                         [0] u16 command
2255                         [2] u8 count
2256                         [3] v3s16 pos_0
2257                         [3+6] v3s16 pos_1
2258                         ...
2259                 */
2260
2261                 u16 count = data[2];
2262                 for(u16 i=0; i<count; i++)
2263                 {
2264                         if((s16)datasize < 2+1+(i+1)*6)
2265                                 throw con::InvalidIncomingDataException
2266                                         ("GOTBLOCKS length is too short");
2267                         v3s16 p = readV3S16(&data[2+1+i*6]);
2268                         /*infostream<<"Server: GOTBLOCKS ("
2269                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
2270                         RemoteClient *client = getClient(peer_id);
2271                         client->GotBlock(p);
2272                 }
2273         }
2274         else if(command == TOSERVER_DELETEDBLOCKS)
2275         {
2276                 if(datasize < 2+1)
2277                         return;
2278
2279                 /*
2280                         [0] u16 command
2281                         [2] u8 count
2282                         [3] v3s16 pos_0
2283                         [3+6] v3s16 pos_1
2284                         ...
2285                 */
2286
2287                 u16 count = data[2];
2288                 for(u16 i=0; i<count; i++)
2289                 {
2290                         if((s16)datasize < 2+1+(i+1)*6)
2291                                 throw con::InvalidIncomingDataException
2292                                         ("DELETEDBLOCKS length is too short");
2293                         v3s16 p = readV3S16(&data[2+1+i*6]);
2294                         /*infostream<<"Server: DELETEDBLOCKS ("
2295                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
2296                         RemoteClient *client = getClient(peer_id);
2297                         client->SetBlockNotSent(p);
2298                 }
2299         }
2300         else if(command == TOSERVER_CLICK_OBJECT)
2301         {
2302                 infostream<<"Server: CLICK_OBJECT not supported anymore"<<std::endl;
2303                 return;
2304         }
2305         else if(command == TOSERVER_CLICK_ACTIVEOBJECT)
2306         {
2307                 infostream<<"Server: CLICK_ACTIVEOBJECT not supported anymore"<<std::endl;
2308                 return;
2309         }
2310         else if(command == TOSERVER_GROUND_ACTION)
2311         {
2312                 infostream<<"Server: GROUND_ACTION not supported anymore"<<std::endl;
2313                 return;
2314
2315         }
2316         else if(command == TOSERVER_RELEASE)
2317         {
2318                 infostream<<"Server: RELEASE not supported anymore"<<std::endl;
2319                 return;
2320         }
2321         else if(command == TOSERVER_SIGNTEXT)
2322         {
2323                 infostream<<"Server: SIGNTEXT not supported anymore"
2324                                 <<std::endl;
2325                 return;
2326         }
2327         else if(command == TOSERVER_SIGNNODETEXT)
2328         {
2329                 infostream<<"Server: SIGNNODETEXT not supported anymore"
2330                                 <<std::endl;
2331                 return;
2332         }
2333         else if(command == TOSERVER_INVENTORY_ACTION)
2334         {
2335                 // Strip command and create a stream
2336                 std::string datastring((char*)&data[2], datasize-2);
2337                 verbosestream<<"TOSERVER_INVENTORY_ACTION: data="<<datastring<<std::endl;
2338                 std::istringstream is(datastring, std::ios_base::binary);
2339                 // Create an action
2340                 InventoryAction *a = InventoryAction::deSerialize(is);
2341                 if(a == NULL)
2342                 {
2343                         infostream<<"TOSERVER_INVENTORY_ACTION: "
2344                                         <<"InventoryAction::deSerialize() returned NULL"
2345                                         <<std::endl;
2346                         return;
2347                 }
2348
2349                 // If something goes wrong, this player is to blame
2350                 RollbackScopeActor rollback_scope(m_rollback,
2351                                 std::string("player:")+player->getName());
2352
2353                 /*
2354                         Note: Always set inventory not sent, to repair cases
2355                         where the client made a bad prediction.
2356                 */
2357
2358                 /*
2359                         Handle restrictions and special cases of the move action
2360                 */
2361                 if(a->getType() == IACTION_MOVE)
2362                 {
2363                         IMoveAction *ma = (IMoveAction*)a;
2364
2365                         ma->from_inv.applyCurrentPlayer(player->getName());
2366                         ma->to_inv.applyCurrentPlayer(player->getName());
2367
2368                         setInventoryModified(ma->from_inv);
2369                         setInventoryModified(ma->to_inv);
2370
2371                         bool from_inv_is_current_player =
2372                                 (ma->from_inv.type == InventoryLocation::PLAYER) &&
2373                                 (ma->from_inv.name == player->getName());
2374
2375                         bool to_inv_is_current_player =
2376                                 (ma->to_inv.type == InventoryLocation::PLAYER) &&
2377                                 (ma->to_inv.name == player->getName());
2378
2379                         /*
2380                                 Disable moving items out of craftpreview
2381                         */
2382                         if(ma->from_list == "craftpreview")
2383                         {
2384                                 infostream<<"Ignoring IMoveAction from "
2385                                                 <<(ma->from_inv.dump())<<":"<<ma->from_list
2386                                                 <<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
2387                                                 <<" because src is "<<ma->from_list<<std::endl;
2388                                 delete a;
2389                                 return;
2390                         }
2391
2392                         /*
2393                                 Disable moving items into craftresult and craftpreview
2394                         */
2395                         if(ma->to_list == "craftpreview" || ma->to_list == "craftresult")
2396                         {
2397                                 infostream<<"Ignoring IMoveAction from "
2398                                                 <<(ma->from_inv.dump())<<":"<<ma->from_list
2399                                                 <<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
2400                                                 <<" because dst is "<<ma->to_list<<std::endl;
2401                                 delete a;
2402                                 return;
2403                         }
2404
2405                         // Disallow moving items in elsewhere than player's inventory
2406                         // if not allowed to interact
2407                         if(!checkPriv(player->getName(), "interact") &&
2408                                         (!from_inv_is_current_player ||
2409                                         !to_inv_is_current_player))
2410                         {
2411                                 infostream<<"Cannot move outside of player's inventory: "
2412                                                 <<"No interact privilege"<<std::endl;
2413                                 delete a;
2414                                 return;
2415                         }
2416                 }
2417                 /*
2418                         Handle restrictions and special cases of the drop action
2419                 */
2420                 else if(a->getType() == IACTION_DROP)
2421                 {
2422                         IDropAction *da = (IDropAction*)a;
2423
2424                         da->from_inv.applyCurrentPlayer(player->getName());
2425
2426                         setInventoryModified(da->from_inv);
2427
2428                         /*
2429                                 Disable dropping items out of craftpreview
2430                         */
2431                         if(da->from_list == "craftpreview")
2432                         {
2433                                 infostream<<"Ignoring IDropAction from "
2434                                                 <<(da->from_inv.dump())<<":"<<da->from_list
2435                                                 <<" because src is "<<da->from_list<<std::endl;
2436                                 delete a;
2437                                 return;
2438                         }
2439
2440                         // Disallow dropping items if not allowed to interact
2441                         if(!checkPriv(player->getName(), "interact"))
2442                         {
2443                                 delete a;
2444                                 return;
2445                         }
2446                 }
2447                 /*
2448                         Handle restrictions and special cases of the craft action
2449                 */
2450                 else if(a->getType() == IACTION_CRAFT)
2451                 {
2452                         ICraftAction *ca = (ICraftAction*)a;
2453
2454                         ca->craft_inv.applyCurrentPlayer(player->getName());
2455
2456                         setInventoryModified(ca->craft_inv);
2457
2458                         //bool craft_inv_is_current_player =
2459                         //      (ca->craft_inv.type == InventoryLocation::PLAYER) &&
2460                         //      (ca->craft_inv.name == player->getName());
2461
2462                         // Disallow crafting if not allowed to interact
2463                         if(!checkPriv(player->getName(), "interact"))
2464                         {
2465                                 infostream<<"Cannot craft: "
2466                                                 <<"No interact privilege"<<std::endl;
2467                                 delete a;
2468                                 return;
2469                         }
2470                 }
2471
2472                 // Do the action
2473                 a->apply(this, playersao, this);
2474                 // Eat the action
2475                 delete a;
2476         }
2477         else if(command == TOSERVER_CHAT_MESSAGE)
2478         {
2479                 /*
2480                         u16 command
2481                         u16 length
2482                         wstring message
2483                 */
2484                 u8 buf[6];
2485                 std::string datastring((char*)&data[2], datasize-2);
2486                 std::istringstream is(datastring, std::ios_base::binary);
2487
2488                 // Read stuff
2489                 is.read((char*)buf, 2);
2490                 u16 len = readU16(buf);
2491
2492                 std::wstring message;
2493                 for(u16 i=0; i<len; i++)
2494                 {
2495                         is.read((char*)buf, 2);
2496                         message += (wchar_t)readU16(buf);
2497                 }
2498
2499                 // If something goes wrong, this player is to blame
2500                 RollbackScopeActor rollback_scope(m_rollback,
2501                                 std::string("player:")+player->getName());
2502
2503                 // Get player name of this client
2504                 std::wstring name = narrow_to_wide(player->getName());
2505
2506                 // Run script hook
2507                 bool ate = m_script->on_chat_message(player->getName(),
2508                                 wide_to_narrow(message));
2509                 // If script ate the message, don't proceed
2510                 if(ate)
2511                         return;
2512
2513                 // Line to send to players
2514                 std::wstring line;
2515                 // Whether to send to the player that sent the line
2516                 bool send_to_sender = false;
2517                 // Whether to send to other players
2518                 bool send_to_others = false;
2519
2520                 // Commands are implemented in Lua, so only catch invalid
2521                 // commands that were not "eaten" and send an error back
2522                 if(message[0] == L'/')
2523                 {
2524                         message = message.substr(1);
2525                         send_to_sender = true;
2526                         if(message.length() == 0)
2527                                 line += L"-!- Empty command";
2528                         else
2529                                 line += L"-!- Invalid command: " + str_split(message, L' ')[0];
2530                 }
2531                 else
2532                 {
2533                         if(checkPriv(player->getName(), "shout")){
2534                                 line += L"<";
2535                                 line += name;
2536                                 line += L"> ";
2537                                 line += message;
2538                                 send_to_others = true;
2539                         } else {
2540                                 line += L"-!- You don't have permission to shout.";
2541                                 send_to_sender = true;
2542                         }
2543                 }
2544
2545                 if(line != L"")
2546                 {
2547                         if(send_to_others)
2548                                 actionstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
2549
2550                         /*
2551                                 Send the message to clients
2552                         */
2553                         for(std::map<u16, RemoteClient*>::iterator
2554                                 i = m_clients.begin();
2555                                 i != m_clients.end(); ++i)
2556                         {
2557                                 // Get client and check that it is valid
2558                                 RemoteClient *client = i->second;
2559                                 assert(client->peer_id == i->first);
2560                                 if(client->serialization_version == SER_FMT_VER_INVALID)
2561                                         continue;
2562
2563                                 // Filter recipient
2564                                 bool sender_selected = (peer_id == client->peer_id);
2565                                 if(sender_selected == true && send_to_sender == false)
2566                                         continue;
2567                                 if(sender_selected == false && send_to_others == false)
2568                                         continue;
2569
2570                                 SendChatMessage(client->peer_id, line);
2571                         }
2572                 }
2573         }
2574         else if(command == TOSERVER_DAMAGE)
2575         {
2576                 std::string datastring((char*)&data[2], datasize-2);
2577                 std::istringstream is(datastring, std::ios_base::binary);
2578                 u8 damage = readU8(is);
2579
2580                 if(g_settings->getBool("enable_damage"))
2581                 {
2582                         actionstream<<player->getName()<<" damaged by "
2583                                         <<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
2584                                         <<std::endl;
2585
2586                         playersao->setHP(playersao->getHP() - damage);
2587
2588                         if(playersao->getHP() == 0 && playersao->m_hp_not_sent)
2589                                 DiePlayer(peer_id);
2590
2591                         if(playersao->m_hp_not_sent)
2592                                 SendPlayerHP(peer_id);
2593                 }
2594         }
2595         else if(command == TOSERVER_BREATH)
2596         {
2597                 std::string datastring((char*)&data[2], datasize-2);
2598                 std::istringstream is(datastring, std::ios_base::binary);
2599                 u16 breath = readU16(is);
2600                 playersao->setBreath(breath);
2601         }
2602         else if(command == TOSERVER_PASSWORD)
2603         {
2604                 /*
2605                         [0] u16 TOSERVER_PASSWORD
2606                         [2] u8[28] old password
2607                         [30] u8[28] new password
2608                 */
2609
2610                 if(datasize != 2+PASSWORD_SIZE*2)
2611                         return;
2612                 /*char password[PASSWORD_SIZE];
2613                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2614                         password[i] = data[2+i];
2615                 password[PASSWORD_SIZE-1] = 0;*/
2616                 std::string oldpwd;
2617                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2618                 {
2619                         char c = data[2+i];
2620                         if(c == 0)
2621                                 break;
2622                         oldpwd += c;
2623                 }
2624                 std::string newpwd;
2625                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2626                 {
2627                         char c = data[2+PASSWORD_SIZE+i];
2628                         if(c == 0)
2629                                 break;
2630                         newpwd += c;
2631                 }
2632
2633                 if(!base64_is_valid(newpwd)){
2634                         infostream<<"Server: "<<player->getName()<<" supplied invalid password hash"<<std::endl;
2635                         // Wrong old password supplied!!
2636                         SendChatMessage(peer_id, L"Invalid new password hash supplied. Password NOT changed.");
2637                         return;
2638                 }
2639
2640                 infostream<<"Server: Client requests a password change from "
2641                                 <<"'"<<oldpwd<<"' to '"<<newpwd<<"'"<<std::endl;
2642
2643                 std::string playername = player->getName();
2644
2645                 std::string checkpwd;
2646                 m_script->getAuth(playername, &checkpwd, NULL);
2647
2648                 if(oldpwd != checkpwd)
2649                 {
2650                         infostream<<"Server: invalid old password"<<std::endl;
2651                         // Wrong old password supplied!!
2652                         SendChatMessage(peer_id, L"Invalid old password supplied. Password NOT changed.");
2653                         return;
2654                 }
2655
2656                 bool success = m_script->setPassword(playername, newpwd);
2657                 if(success){
2658                         actionstream<<player->getName()<<" changes password"<<std::endl;
2659                         SendChatMessage(peer_id, L"Password change successful.");
2660                 } else {
2661                         actionstream<<player->getName()<<" tries to change password but "
2662                                         <<"it fails"<<std::endl;
2663                         SendChatMessage(peer_id, L"Password change failed or inavailable.");
2664                 }
2665         }
2666         else if(command == TOSERVER_PLAYERITEM)
2667         {
2668                 if (datasize < 2+2)
2669                         return;
2670
2671                 u16 item = readU16(&data[2]);
2672                 playersao->setWieldIndex(item);
2673         }
2674         else if(command == TOSERVER_RESPAWN)
2675         {
2676                 if(player->hp != 0 || !g_settings->getBool("enable_damage"))
2677                         return;
2678
2679                 RespawnPlayer(peer_id);
2680
2681                 actionstream<<player->getName()<<" respawns at "
2682                                 <<PP(player->getPosition()/BS)<<std::endl;
2683
2684                 // ActiveObject is added to environment in AsyncRunStep after
2685                 // the previous addition has been succesfully removed
2686         }
2687         else if(command == TOSERVER_REQUEST_MEDIA) {
2688                 std::string datastring((char*)&data[2], datasize-2);
2689                 std::istringstream is(datastring, std::ios_base::binary);
2690
2691                 std::list<MediaRequest> tosend;
2692                 u16 numfiles = readU16(is);
2693
2694                 infostream<<"Sending "<<numfiles<<" files to "
2695                                 <<getPlayerName(peer_id)<<std::endl;
2696                 verbosestream<<"TOSERVER_REQUEST_MEDIA: "<<std::endl;
2697
2698                 for(int i = 0; i < numfiles; i++) {
2699                         std::string name = deSerializeString(is);
2700                         tosend.push_back(MediaRequest(name));
2701                         verbosestream<<"TOSERVER_REQUEST_MEDIA: requested file "
2702                                         <<name<<std::endl;
2703                 }
2704
2705                 sendRequestedMedia(peer_id, tosend);
2706
2707                 // Now the client should know about everything
2708                 // (definitions and files)
2709                 getClient(peer_id)->definitions_sent = true;
2710         }
2711         else if(command == TOSERVER_RECEIVED_MEDIA) {
2712                 getClient(peer_id)->definitions_sent = true;
2713         }
2714         else if(command == TOSERVER_INTERACT)
2715         {
2716                 std::string datastring((char*)&data[2], datasize-2);
2717                 std::istringstream is(datastring, std::ios_base::binary);
2718
2719                 /*
2720                         [0] u16 command
2721                         [2] u8 action
2722                         [3] u16 item
2723                         [5] u32 length of the next item
2724                         [9] serialized PointedThing
2725                         actions:
2726                         0: start digging (from undersurface) or use
2727                         1: stop digging (all parameters ignored)
2728                         2: digging completed
2729                         3: place block or item (to abovesurface)
2730                         4: use item
2731                 */
2732                 u8 action = readU8(is);
2733                 u16 item_i = readU16(is);
2734                 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
2735                 PointedThing pointed;
2736                 pointed.deSerialize(tmp_is);
2737
2738                 verbosestream<<"TOSERVER_INTERACT: action="<<(int)action<<", item="
2739                                 <<item_i<<", pointed="<<pointed.dump()<<std::endl;
2740
2741                 if(player->hp == 0)
2742                 {
2743                         verbosestream<<"TOSERVER_INTERACT: "<<player->getName()
2744                                 <<" tried to interact, but is dead!"<<std::endl;
2745                         return;
2746                 }
2747
2748                 v3f player_pos = playersao->getLastGoodPosition();
2749
2750                 // Update wielded item
2751                 playersao->setWieldIndex(item_i);
2752
2753                 // Get pointed to node (undefined if not POINTEDTYPE_NODE)
2754                 v3s16 p_under = pointed.node_undersurface;
2755                 v3s16 p_above = pointed.node_abovesurface;
2756
2757                 // Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
2758                 ServerActiveObject *pointed_object = NULL;
2759                 if(pointed.type == POINTEDTHING_OBJECT)
2760                 {
2761                         pointed_object = m_env->getActiveObject(pointed.object_id);
2762                         if(pointed_object == NULL)
2763                         {
2764                                 verbosestream<<"TOSERVER_INTERACT: "
2765                                         "pointed object is NULL"<<std::endl;
2766                                 return;
2767                         }
2768
2769                 }
2770
2771                 v3f pointed_pos_under = player_pos;
2772                 v3f pointed_pos_above = player_pos;
2773                 if(pointed.type == POINTEDTHING_NODE)
2774                 {
2775                         pointed_pos_under = intToFloat(p_under, BS);
2776                         pointed_pos_above = intToFloat(p_above, BS);
2777                 }
2778                 else if(pointed.type == POINTEDTHING_OBJECT)
2779                 {
2780                         pointed_pos_under = pointed_object->getBasePosition();
2781                         pointed_pos_above = pointed_pos_under;
2782                 }
2783
2784                 /*
2785                         Check that target is reasonably close
2786                         (only when digging or placing things)
2787                 */
2788                 if(action == 0 || action == 2 || action == 3)
2789                 {
2790                         float d = player_pos.getDistanceFrom(pointed_pos_under);
2791                         float max_d = BS * 14; // Just some large enough value
2792                         if(d > max_d){
2793                                 actionstream<<"Player "<<player->getName()
2794                                                 <<" tried to access "<<pointed.dump()
2795                                                 <<" from too far: "
2796                                                 <<"d="<<d<<", max_d="<<max_d
2797                                                 <<". ignoring."<<std::endl;
2798                                 // Re-send block to revert change on client-side
2799                                 RemoteClient *client = getClient(peer_id);
2800                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2801                                 client->SetBlockNotSent(blockpos);
2802                                 // Do nothing else
2803                                 return;
2804                         }
2805                 }
2806
2807                 /*
2808                         Make sure the player is allowed to do it
2809                 */
2810                 if(!checkPriv(player->getName(), "interact"))
2811                 {
2812                         actionstream<<player->getName()<<" attempted to interact with "
2813                                         <<pointed.dump()<<" without 'interact' privilege"
2814                                         <<std::endl;
2815                         // Re-send block to revert change on client-side
2816                         RemoteClient *client = getClient(peer_id);
2817                         // Digging completed -> under
2818                         if(action == 2){
2819                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2820                                 client->SetBlockNotSent(blockpos);
2821                         }
2822                         // Placement -> above
2823                         if(action == 3){
2824                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
2825                                 client->SetBlockNotSent(blockpos);
2826                         }
2827                         return;
2828                 }
2829
2830                 /*
2831                         If something goes wrong, this player is to blame
2832                 */
2833                 RollbackScopeActor rollback_scope(m_rollback,
2834                                 std::string("player:")+player->getName());
2835
2836                 /*
2837                         0: start digging or punch object
2838                 */
2839                 if(action == 0)
2840                 {
2841                         if(pointed.type == POINTEDTHING_NODE)
2842                         {
2843                                 /*
2844                                         NOTE: This can be used in the future to check if
2845                                         somebody is cheating, by checking the timing.
2846                                 */
2847                                 MapNode n(CONTENT_IGNORE);
2848                                 try
2849                                 {
2850                                         n = m_env->getMap().getNode(p_under);
2851                                 }
2852                                 catch(InvalidPositionException &e)
2853                                 {
2854                                         infostream<<"Server: Not punching: Node not found."
2855                                                         <<" Adding block to emerge queue."
2856                                                         <<std::endl;
2857                                         m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2858                                 }
2859                                 if(n.getContent() != CONTENT_IGNORE)
2860                                         m_script->node_on_punch(p_under, n, playersao);
2861                                 // Cheat prevention
2862                                 playersao->noCheatDigStart(p_under);
2863                         }
2864                         else if(pointed.type == POINTEDTHING_OBJECT)
2865                         {
2866                                 // Skip if object has been removed
2867                                 if(pointed_object->m_removed)
2868                                         return;
2869
2870                                 actionstream<<player->getName()<<" punches object "
2871                                                 <<pointed.object_id<<": "
2872                                                 <<pointed_object->getDescription()<<std::endl;
2873
2874                                 ItemStack punchitem = playersao->getWieldedItem();
2875                                 ToolCapabilities toolcap =
2876                                                 punchitem.getToolCapabilities(m_itemdef);
2877                                 v3f dir = (pointed_object->getBasePosition() -
2878                                                 (player->getPosition() + player->getEyeOffset())
2879                                                         ).normalize();
2880                                 float time_from_last_punch =
2881                                         playersao->resetTimeFromLastPunch();
2882                                 pointed_object->punch(dir, &toolcap, playersao,
2883                                                 time_from_last_punch);
2884                         }
2885
2886                 } // action == 0
2887
2888                 /*
2889                         1: stop digging
2890                 */
2891                 else if(action == 1)
2892                 {
2893                 } // action == 1
2894
2895                 /*
2896                         2: Digging completed
2897                 */
2898                 else if(action == 2)
2899                 {
2900                         // Only digging of nodes
2901                         if(pointed.type == POINTEDTHING_NODE)
2902                         {
2903                                 MapNode n(CONTENT_IGNORE);
2904                                 try
2905                                 {
2906                                         n = m_env->getMap().getNode(p_under);
2907                                 }
2908                                 catch(InvalidPositionException &e)
2909                                 {
2910                                         infostream<<"Server: Not finishing digging: Node not found."
2911                                                         <<" Adding block to emerge queue."
2912                                                         <<std::endl;
2913                                         m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2914                                 }
2915
2916                                 /* Cheat prevention */
2917                                 bool is_valid_dig = true;
2918                                 if(!isSingleplayer() && !g_settings->getBool("disable_anticheat"))
2919                                 {
2920                                         v3s16 nocheat_p = playersao->getNoCheatDigPos();
2921                                         float nocheat_t = playersao->getNoCheatDigTime();
2922                                         playersao->noCheatDigEnd();
2923                                         // If player didn't start digging this, ignore dig
2924                                         if(nocheat_p != p_under){
2925                                                 infostream<<"Server: NoCheat: "<<player->getName()
2926                                                                 <<" started digging "
2927                                                                 <<PP(nocheat_p)<<" and completed digging "
2928                                                                 <<PP(p_under)<<"; not digging."<<std::endl;
2929                                                 is_valid_dig = false;
2930                                         }
2931                                         // Get player's wielded item
2932                                         ItemStack playeritem;
2933                                         InventoryList *mlist = playersao->getInventory()->getList("main");
2934                                         if(mlist != NULL)
2935                                                 playeritem = mlist->getItem(playersao->getWieldIndex());
2936                                         ToolCapabilities playeritem_toolcap =
2937                                                         playeritem.getToolCapabilities(m_itemdef);
2938                                         // Get diggability and expected digging time
2939                                         DigParams params = getDigParams(m_nodedef->get(n).groups,
2940                                                         &playeritem_toolcap);
2941                                         // If can't dig, try hand
2942                                         if(!params.diggable){
2943                                                 const ItemDefinition &hand = m_itemdef->get("");
2944                                                 const ToolCapabilities *tp = hand.tool_capabilities;
2945                                                 if(tp)
2946                                                         params = getDigParams(m_nodedef->get(n).groups, tp);
2947                                         }
2948                                         // If can't dig, ignore dig
2949                                         if(!params.diggable){
2950                                                 infostream<<"Server: NoCheat: "<<player->getName()
2951                                                                 <<" completed digging "<<PP(p_under)
2952                                                                 <<", which is not diggable with tool. not digging."
2953                                                                 <<std::endl;
2954                                                 is_valid_dig = false;
2955                                         }
2956                                         // If time is considerably too short, ignore dig
2957                                         // Check time only for medium and slow timed digs
2958                                         if(params.diggable && params.time > 0.3 && nocheat_t < 0.5 * params.time){
2959                                                 infostream<<"Server: NoCheat: "<<player->getName()
2960                                                                 <<" completed digging "
2961                                                                 <<PP(p_under)<<" in "<<nocheat_t<<"s; expected "
2962                                                                 <<params.time<<"s; not digging."<<std::endl;
2963                                                 is_valid_dig = false;
2964                                         }
2965                                 }
2966
2967                                 /* Actually dig node */
2968
2969                                 if(is_valid_dig && n.getContent() != CONTENT_IGNORE)
2970                                         m_script->node_on_dig(p_under, n, playersao);
2971
2972                                 // Send unusual result (that is, node not being removed)
2973                                 if(m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR)
2974                                 {
2975                                         // Re-send block to revert change on client-side
2976                                         RemoteClient *client = getClient(peer_id);
2977                                         v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2978                                         client->SetBlockNotSent(blockpos);
2979                                 }
2980                         }
2981                 } // action == 2
2982
2983                 /*
2984                         3: place block or right-click object
2985                 */
2986                 else if(action == 3)
2987                 {
2988                         ItemStack item = playersao->getWieldedItem();
2989
2990                         // Reset build time counter
2991                         if(pointed.type == POINTEDTHING_NODE &&
2992                                         item.getDefinition(m_itemdef).type == ITEM_NODE)
2993                                 getClient(peer_id)->m_time_from_building = 0.0;
2994
2995                         if(pointed.type == POINTEDTHING_OBJECT)
2996                         {
2997                                 // Right click object
2998
2999                                 // Skip if object has been removed
3000                                 if(pointed_object->m_removed)
3001                                         return;
3002
3003                                 actionstream<<player->getName()<<" right-clicks object "
3004                                                 <<pointed.object_id<<": "
3005                                                 <<pointed_object->getDescription()<<std::endl;
3006
3007                                 // Do stuff
3008                                 pointed_object->rightClick(playersao);
3009                         }
3010                         else if(m_script->item_OnPlace(
3011                                         item, playersao, pointed))
3012                         {
3013                                 // Placement was handled in lua
3014
3015                                 // Apply returned ItemStack
3016                                 playersao->setWieldedItem(item);
3017                         }
3018
3019                         // If item has node placement prediction, always send the
3020                         // blocks to make sure the client knows what exactly happened
3021                         if(item.getDefinition(m_itemdef).node_placement_prediction != ""){
3022                                 RemoteClient *client = getClient(peer_id);
3023                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
3024                                 client->SetBlockNotSent(blockpos);
3025                                 v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
3026                                 if(blockpos2 != blockpos){
3027                                         client->SetBlockNotSent(blockpos2);
3028                                 }
3029                         }
3030                 } // action == 3
3031
3032                 /*
3033                         4: use
3034                 */
3035                 else if(action == 4)
3036                 {
3037                         ItemStack item = playersao->getWieldedItem();
3038
3039                         actionstream<<player->getName()<<" uses "<<item.name
3040                                         <<", pointing at "<<pointed.dump()<<std::endl;
3041
3042                         if(m_script->item_OnUse(
3043                                         item, playersao, pointed))
3044                         {
3045                                 // Apply returned ItemStack
3046                                 playersao->setWieldedItem(item);
3047                         }
3048
3049                 } // action == 4
3050                 
3051
3052                 /*
3053                         Catch invalid actions
3054                 */
3055                 else
3056                 {
3057                         infostream<<"WARNING: Server: Invalid action "
3058                                         <<action<<std::endl;
3059                 }
3060         }
3061         else if(command == TOSERVER_REMOVED_SOUNDS)
3062         {
3063                 std::string datastring((char*)&data[2], datasize-2);
3064                 std::istringstream is(datastring, std::ios_base::binary);
3065
3066                 int num = readU16(is);
3067                 for(int k=0; k<num; k++){
3068                         s32 id = readS32(is);
3069                         std::map<s32, ServerPlayingSound>::iterator i =
3070                                         m_playing_sounds.find(id);
3071                         if(i == m_playing_sounds.end())
3072                                 continue;
3073                         ServerPlayingSound &psound = i->second;
3074                         psound.clients.erase(peer_id);
3075                         if(psound.clients.size() == 0)
3076                                 m_playing_sounds.erase(i++);
3077                 }
3078         }
3079         else if(command == TOSERVER_NODEMETA_FIELDS)
3080         {
3081                 std::string datastring((char*)&data[2], datasize-2);
3082                 std::istringstream is(datastring, std::ios_base::binary);
3083
3084                 v3s16 p = readV3S16(is);
3085                 std::string formname = deSerializeString(is);
3086                 int num = readU16(is);
3087                 std::map<std::string, std::string> fields;
3088                 for(int k=0; k<num; k++){
3089                         std::string fieldname = deSerializeString(is);
3090                         std::string fieldvalue = deSerializeLongString(is);
3091                         fields[fieldname] = fieldvalue;
3092                 }
3093
3094                 // If something goes wrong, this player is to blame
3095                 RollbackScopeActor rollback_scope(m_rollback,
3096                                 std::string("player:")+player->getName());
3097
3098                 // Check the target node for rollback data; leave others unnoticed
3099                 RollbackNode rn_old(&m_env->getMap(), p, this);
3100
3101                 m_script->node_on_receive_fields(p, formname, fields,playersao);
3102
3103                 // Report rollback data
3104                 RollbackNode rn_new(&m_env->getMap(), p, this);
3105                 if(rollback() && rn_new != rn_old){
3106                         RollbackAction action;
3107                         action.setSetNode(p, rn_old, rn_new);
3108                         rollback()->reportAction(action);
3109                 }
3110         }
3111         else if(command == TOSERVER_INVENTORY_FIELDS)
3112         {
3113                 std::string datastring((char*)&data[2], datasize-2);
3114                 std::istringstream is(datastring, std::ios_base::binary);
3115
3116                 std::string formname = deSerializeString(is);
3117                 int num = readU16(is);
3118                 std::map<std::string, std::string> fields;
3119                 for(int k=0; k<num; k++){
3120                         std::string fieldname = deSerializeString(is);
3121                         std::string fieldvalue = deSerializeLongString(is);
3122                         fields[fieldname] = fieldvalue;
3123                 }
3124
3125                 m_script->on_playerReceiveFields(playersao, formname, fields);
3126         }
3127         else
3128         {
3129                 infostream<<"Server::ProcessData(): Ignoring "
3130                                 "unknown command "<<command<<std::endl;
3131         }
3132
3133         } //try
3134         catch(SendFailedException &e)
3135         {
3136                 errorstream<<"Server::ProcessData(): SendFailedException: "
3137                                 <<"what="<<e.what()
3138                                 <<std::endl;
3139         }
3140 }
3141
3142 void Server::onMapEditEvent(MapEditEvent *event)
3143 {
3144         //infostream<<"Server::onMapEditEvent()"<<std::endl;
3145         if(m_ignore_map_edit_events)
3146                 return;
3147         if(m_ignore_map_edit_events_area.contains(event->getArea()))
3148                 return;
3149         MapEditEvent *e = event->clone();
3150         m_unsent_map_edit_queue.push_back(e);
3151 }
3152
3153 Inventory* Server::getInventory(const InventoryLocation &loc)
3154 {
3155         switch(loc.type){
3156         case InventoryLocation::UNDEFINED:
3157         {}
3158         break;
3159         case InventoryLocation::CURRENT_PLAYER:
3160         {}
3161         break;
3162         case InventoryLocation::PLAYER:
3163         {
3164                 Player *player = m_env->getPlayer(loc.name.c_str());
3165                 if(!player)
3166                         return NULL;
3167                 PlayerSAO *playersao = player->getPlayerSAO();
3168                 if(!playersao)
3169                         return NULL;
3170                 return playersao->getInventory();
3171         }
3172         break;
3173         case InventoryLocation::NODEMETA:
3174         {
3175                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3176                 if(!meta)
3177                         return NULL;
3178                 return meta->getInventory();
3179         }
3180         break;
3181         case InventoryLocation::DETACHED:
3182         {
3183                 if(m_detached_inventories.count(loc.name) == 0)
3184                         return NULL;
3185                 return m_detached_inventories[loc.name];
3186         }
3187         break;
3188         default:
3189                 assert(0);
3190         }
3191         return NULL;
3192 }
3193 void Server::setInventoryModified(const InventoryLocation &loc)
3194 {
3195         switch(loc.type){
3196         case InventoryLocation::UNDEFINED:
3197         {}
3198         break;
3199         case InventoryLocation::PLAYER:
3200         {
3201                 Player *player = m_env->getPlayer(loc.name.c_str());
3202                 if(!player)
3203                         return;
3204                 PlayerSAO *playersao = player->getPlayerSAO();
3205                 if(!playersao)
3206                         return;
3207                 playersao->m_inventory_not_sent = true;
3208                 playersao->m_wielded_item_not_sent = true;
3209         }
3210         break;
3211         case InventoryLocation::NODEMETA:
3212         {
3213                 v3s16 blockpos = getNodeBlockPos(loc.p);
3214
3215                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
3216                 if(block)
3217                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
3218
3219                 setBlockNotSent(blockpos);
3220         }
3221         break;
3222         case InventoryLocation::DETACHED:
3223         {
3224                 sendDetachedInventoryToAll(loc.name);
3225         }
3226         break;
3227         default:
3228                 assert(0);
3229         }
3230 }
3231
3232 //std::list<PlayerInfo> Server::getPlayerInfo()
3233 //{
3234 //      DSTACK(__FUNCTION_NAME);
3235 //      JMutexAutoLock envlock(m_env_mutex);
3236 //      JMutexAutoLock conlock(m_con_mutex);
3237 //
3238 //      std::list<PlayerInfo> list;
3239 //
3240 //      std::list<Player*> players = m_env->getPlayers();
3241 //
3242 //      std::list<Player*>::iterator i;
3243 //      for(i = players.begin();
3244 //                      i != players.end(); ++i)
3245 //      {
3246 //              PlayerInfo info;
3247 //
3248 //              Player *player = *i;
3249 //
3250 //              try{
3251 //                      // Copy info from connection to info struct
3252 //                      info.id = player->peer_id;
3253 //                      info.address = m_con.GetPeerAddress(player->peer_id);
3254 //                      info.avg_rtt = m_con.GetPeerAvgRTT(player->peer_id);
3255 //              }
3256 //              catch(con::PeerNotFoundException &e)
3257 //              {
3258 //                      // Set dummy peer info
3259 //                      info.id = 0;
3260 //                      info.address = Address(0,0,0,0,0);
3261 //                      info.avg_rtt = 0.0;
3262 //              }
3263 //
3264 //              snprintf(info.name, PLAYERNAME_SIZE, "%s", player->getName());
3265 //              info.position = player->getPosition();
3266 //
3267 //              list.push_back(info);
3268 //      }
3269 //
3270 //      return list;
3271 //}
3272
3273
3274 void Server::peerAdded(con::Peer *peer)
3275 {
3276         DSTACK(__FUNCTION_NAME);
3277         verbosestream<<"Server::peerAdded(): peer->id="
3278                         <<peer->id<<std::endl;
3279
3280         PeerChange c;
3281         c.type = PEER_ADDED;
3282         c.peer_id = peer->id;
3283         c.timeout = false;
3284         m_peer_change_queue.push_back(c);
3285 }
3286
3287 void Server::deletingPeer(con::Peer *peer, bool timeout)
3288 {
3289         DSTACK(__FUNCTION_NAME);
3290         verbosestream<<"Server::deletingPeer(): peer->id="
3291                         <<peer->id<<", timeout="<<timeout<<std::endl;
3292
3293         PeerChange c;
3294         c.type = PEER_REMOVED;
3295         c.peer_id = peer->id;
3296         c.timeout = timeout;
3297         m_peer_change_queue.push_back(c);
3298 }
3299
3300 /*
3301         Static send methods
3302 */
3303
3304 void Server::SendMovement(con::Connection &con, u16 peer_id)
3305 {
3306         DSTACK(__FUNCTION_NAME);
3307         std::ostringstream os(std::ios_base::binary);
3308
3309         writeU16(os, TOCLIENT_MOVEMENT);
3310         writeF1000(os, g_settings->getFloat("movement_acceleration_default"));
3311         writeF1000(os, g_settings->getFloat("movement_acceleration_air"));
3312         writeF1000(os, g_settings->getFloat("movement_acceleration_fast"));
3313         writeF1000(os, g_settings->getFloat("movement_speed_walk"));
3314         writeF1000(os, g_settings->getFloat("movement_speed_crouch"));
3315         writeF1000(os, g_settings->getFloat("movement_speed_fast"));
3316         writeF1000(os, g_settings->getFloat("movement_speed_climb"));
3317         writeF1000(os, g_settings->getFloat("movement_speed_jump"));
3318         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity"));
3319         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity_smooth"));
3320         writeF1000(os, g_settings->getFloat("movement_liquid_sink"));
3321         writeF1000(os, g_settings->getFloat("movement_gravity"));
3322
3323         // Make data buffer
3324         std::string s = os.str();
3325         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3326         // Send as reliable
3327         con.Send(peer_id, 0, data, true);
3328 }
3329
3330 void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp)
3331 {
3332         DSTACK(__FUNCTION_NAME);
3333         std::ostringstream os(std::ios_base::binary);
3334
3335         writeU16(os, TOCLIENT_HP);
3336         writeU8(os, hp);
3337
3338         // Make data buffer
3339         std::string s = os.str();
3340         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3341         // Send as reliable
3342         con.Send(peer_id, 0, data, true);
3343 }
3344
3345 void Server::SendBreath(con::Connection &con, u16 peer_id, u16 breath)
3346 {
3347         DSTACK(__FUNCTION_NAME);
3348         std::ostringstream os(std::ios_base::binary);
3349
3350         writeU16(os, TOCLIENT_BREATH);
3351         writeU16(os, breath);
3352
3353         // Make data buffer
3354         std::string s = os.str();
3355         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3356         // Send as reliable
3357         con.Send(peer_id, 0, data, true);
3358 }
3359
3360 void Server::SendAccessDenied(con::Connection &con, u16 peer_id,
3361                 const std::wstring &reason)
3362 {
3363         DSTACK(__FUNCTION_NAME);
3364         std::ostringstream os(std::ios_base::binary);
3365
3366         writeU16(os, TOCLIENT_ACCESS_DENIED);
3367         os<<serializeWideString(reason);
3368
3369         // Make data buffer
3370         std::string s = os.str();
3371         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3372         // Send as reliable
3373         con.Send(peer_id, 0, data, true);
3374 }
3375
3376 void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
3377                 bool set_camera_point_target, v3f camera_point_target)
3378 {
3379         DSTACK(__FUNCTION_NAME);
3380         std::ostringstream os(std::ios_base::binary);
3381
3382         writeU16(os, TOCLIENT_DEATHSCREEN);
3383         writeU8(os, set_camera_point_target);
3384         writeV3F1000(os, camera_point_target);
3385
3386         // Make data buffer
3387         std::string s = os.str();
3388         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3389         // Send as reliable
3390         con.Send(peer_id, 0, data, true);
3391 }
3392
3393 void Server::SendItemDef(con::Connection &con, u16 peer_id,
3394                 IItemDefManager *itemdef, u16 protocol_version)
3395 {
3396         DSTACK(__FUNCTION_NAME);
3397         std::ostringstream os(std::ios_base::binary);
3398
3399         /*
3400                 u16 command
3401                 u32 length of the next item
3402                 zlib-compressed serialized ItemDefManager
3403         */
3404         writeU16(os, TOCLIENT_ITEMDEF);
3405         std::ostringstream tmp_os(std::ios::binary);
3406         itemdef->serialize(tmp_os, protocol_version);
3407         std::ostringstream tmp_os2(std::ios::binary);
3408         compressZlib(tmp_os.str(), tmp_os2);
3409         os<<serializeLongString(tmp_os2.str());
3410
3411         // Make data buffer
3412         std::string s = os.str();
3413         verbosestream<<"Server: Sending item definitions to id("<<peer_id
3414                         <<"): size="<<s.size()<<std::endl;
3415         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3416         // Send as reliable
3417         con.Send(peer_id, 0, data, true);
3418 }
3419
3420 void Server::SendNodeDef(con::Connection &con, u16 peer_id,
3421                 INodeDefManager *nodedef, u16 protocol_version)
3422 {
3423         DSTACK(__FUNCTION_NAME);
3424         std::ostringstream os(std::ios_base::binary);
3425
3426         /*
3427                 u16 command
3428                 u32 length of the next item
3429                 zlib-compressed serialized NodeDefManager
3430         */
3431         writeU16(os, TOCLIENT_NODEDEF);
3432         std::ostringstream tmp_os(std::ios::binary);
3433         nodedef->serialize(tmp_os, protocol_version);
3434         std::ostringstream tmp_os2(std::ios::binary);
3435         compressZlib(tmp_os.str(), tmp_os2);
3436         os<<serializeLongString(tmp_os2.str());
3437
3438         // Make data buffer
3439         std::string s = os.str();
3440         verbosestream<<"Server: Sending node definitions to id("<<peer_id
3441                         <<"): size="<<s.size()<<std::endl;
3442         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3443         // Send as reliable
3444         con.Send(peer_id, 0, data, true);
3445 }
3446
3447 /*
3448         Non-static send methods
3449 */
3450
3451 void Server::SendInventory(u16 peer_id)
3452 {
3453         DSTACK(__FUNCTION_NAME);
3454
3455         PlayerSAO *playersao = getPlayerSAO(peer_id);
3456         assert(playersao);
3457
3458         playersao->m_inventory_not_sent = false;
3459
3460         /*
3461                 Serialize it
3462         */
3463
3464         std::ostringstream os;
3465         playersao->getInventory()->serialize(os);
3466
3467         std::string s = os.str();
3468
3469         SharedBuffer<u8> data(s.size()+2);
3470         writeU16(&data[0], TOCLIENT_INVENTORY);
3471         memcpy(&data[2], s.c_str(), s.size());
3472
3473         // Send as reliable
3474         m_con.Send(peer_id, 0, data, true);
3475 }
3476
3477 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
3478 {
3479         DSTACK(__FUNCTION_NAME);
3480
3481         std::ostringstream os(std::ios_base::binary);
3482         u8 buf[12];
3483
3484         // Write command
3485         writeU16(buf, TOCLIENT_CHAT_MESSAGE);
3486         os.write((char*)buf, 2);
3487
3488         // Write length
3489         writeU16(buf, message.size());
3490         os.write((char*)buf, 2);
3491
3492         // Write string
3493         for(u32 i=0; i<message.size(); i++)
3494         {
3495                 u16 w = message[i];
3496                 writeU16(buf, w);
3497                 os.write((char*)buf, 2);
3498         }
3499
3500         // Make data buffer
3501         std::string s = os.str();
3502         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3503         // Send as reliable
3504         m_con.Send(peer_id, 0, data, true);
3505 }
3506
3507 void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec,
3508                                         const std::string formname)
3509 {
3510         DSTACK(__FUNCTION_NAME);
3511
3512         std::ostringstream os(std::ios_base::binary);
3513         u8 buf[12];
3514
3515         // Write command
3516         writeU16(buf, TOCLIENT_SHOW_FORMSPEC);
3517         os.write((char*)buf, 2);
3518         os<<serializeLongString(formspec);
3519         os<<serializeString(formname);
3520
3521         // Make data buffer
3522         std::string s = os.str();
3523         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3524         // Send as reliable
3525         m_con.Send(peer_id, 0, data, true);
3526 }
3527
3528 // Spawns a particle on peer with peer_id
3529 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
3530                                 float expirationtime, float size, bool collisiondetection,
3531                                 std::string texture)
3532 {
3533         DSTACK(__FUNCTION_NAME);
3534
3535         std::ostringstream os(std::ios_base::binary);
3536         writeU16(os, TOCLIENT_SPAWN_PARTICLE);
3537         writeV3F1000(os, pos);
3538         writeV3F1000(os, velocity);
3539         writeV3F1000(os, acceleration);
3540         writeF1000(os, expirationtime);
3541         writeF1000(os, size);
3542         writeU8(os,  collisiondetection);
3543         os<<serializeLongString(texture);
3544
3545         // Make data buffer
3546         std::string s = os.str();
3547         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3548         // Send as reliable
3549         m_con.Send(peer_id, 0, data, true);
3550 }
3551
3552 // Spawns a particle on all peers
3553 void Server::SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
3554                                 float expirationtime, float size, bool collisiondetection,
3555                                 std::string texture)
3556 {
3557         for(std::map<u16, RemoteClient*>::iterator
3558                 i = m_clients.begin();
3559                 i != m_clients.end(); i++)
3560         {
3561                 // Get client and check that it is valid
3562                 RemoteClient *client = i->second;
3563                 assert(client->peer_id == i->first);
3564                 if(client->serialization_version == SER_FMT_VER_INVALID)
3565                         continue;
3566
3567                 SendSpawnParticle(client->peer_id, pos, velocity, acceleration,
3568                         expirationtime, size, collisiondetection, texture);
3569         }
3570 }
3571
3572 // Adds a ParticleSpawner on peer with peer_id
3573 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
3574         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3575         float minsize, float maxsize, bool collisiondetection, std::string texture, u32 id)
3576 {
3577         DSTACK(__FUNCTION_NAME);
3578
3579         std::ostringstream os(std::ios_base::binary);
3580         writeU16(os, TOCLIENT_ADD_PARTICLESPAWNER);
3581
3582         writeU16(os, amount);
3583         writeF1000(os, spawntime);
3584         writeV3F1000(os, minpos);
3585         writeV3F1000(os, maxpos);
3586         writeV3F1000(os, minvel);
3587         writeV3F1000(os, maxvel);
3588         writeV3F1000(os, minacc);
3589         writeV3F1000(os, maxacc);
3590         writeF1000(os, minexptime);
3591         writeF1000(os, maxexptime);
3592         writeF1000(os, minsize);
3593         writeF1000(os, maxsize);
3594         writeU8(os,  collisiondetection);
3595         os<<serializeLongString(texture);
3596         writeU32(os, id);
3597
3598         // Make data buffer
3599         std::string s = os.str();
3600         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3601         // Send as reliable
3602         m_con.Send(peer_id, 0, data, true);
3603 }
3604
3605 // Adds a ParticleSpawner on all peers
3606 void Server::SendAddParticleSpawnerAll(u16 amount, float spawntime, v3f minpos, v3f maxpos,
3607         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3608         float minsize, float maxsize, bool collisiondetection, std::string texture, u32 id)
3609 {
3610         for(std::map<u16, RemoteClient*>::iterator
3611                 i = m_clients.begin();
3612                 i != m_clients.end(); i++)
3613         {
3614                 // Get client and check that it is valid
3615                 RemoteClient *client = i->second;
3616                 assert(client->peer_id == i->first);
3617                 if(client->serialization_version == SER_FMT_VER_INVALID)
3618                         continue;
3619
3620                 SendAddParticleSpawner(client->peer_id, amount, spawntime,
3621                         minpos, maxpos, minvel, maxvel, minacc, maxacc,
3622                         minexptime, maxexptime, minsize, maxsize, collisiondetection, texture, id);
3623         }
3624 }
3625
3626 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
3627 {
3628         DSTACK(__FUNCTION_NAME);
3629
3630         std::ostringstream os(std::ios_base::binary);
3631         writeU16(os, TOCLIENT_DELETE_PARTICLESPAWNER);
3632
3633         writeU16(os, id);
3634
3635         // Make data buffer
3636         std::string s = os.str();
3637         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3638         // Send as reliable
3639         m_con.Send(peer_id, 0, data, true);
3640 }
3641
3642 void Server::SendDeleteParticleSpawnerAll(u32 id)
3643 {
3644         for(std::map<u16, RemoteClient*>::iterator
3645                 i = m_clients.begin();
3646                 i != m_clients.end(); i++)
3647         {
3648                 // Get client and check that it is valid
3649                 RemoteClient *client = i->second;
3650                 assert(client->peer_id == i->first);
3651                 if(client->serialization_version == SER_FMT_VER_INVALID)
3652                         continue;
3653
3654                 SendDeleteParticleSpawner(client->peer_id, id);
3655         }
3656 }
3657
3658 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
3659 {
3660         std::ostringstream os(std::ios_base::binary);
3661
3662         // Write command
3663         writeU16(os, TOCLIENT_HUDADD);
3664         writeU32(os, id);
3665         writeU8(os, (u8)form->type);
3666         writeV2F1000(os, form->pos);
3667         os << serializeString(form->name);
3668         writeV2F1000(os, form->scale);
3669         os << serializeString(form->text);
3670         writeU32(os, form->number);
3671         writeU32(os, form->item);
3672         writeU32(os, form->dir);
3673         writeV2F1000(os, form->align);
3674         writeV2F1000(os, form->offset);
3675
3676         // Make data buffer
3677         std::string s = os.str();
3678         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3679         // Send as reliable
3680         m_con.Send(peer_id, 0, data, true);
3681 }
3682
3683 void Server::SendHUDRemove(u16 peer_id, u32 id)
3684 {
3685         std::ostringstream os(std::ios_base::binary);
3686
3687         // Write command
3688         writeU16(os, TOCLIENT_HUDRM);
3689         writeU32(os, id);
3690
3691         // Make data buffer
3692         std::string s = os.str();
3693         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3694         // Send as reliable
3695         m_con.Send(peer_id, 0, data, true);
3696 }
3697
3698 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
3699 {
3700         std::ostringstream os(std::ios_base::binary);
3701
3702         // Write command
3703         writeU16(os, TOCLIENT_HUDCHANGE);
3704         writeU32(os, id);
3705         writeU8(os, (u8)stat);
3706         switch (stat) {
3707                 case HUD_STAT_POS:
3708                 case HUD_STAT_SCALE:
3709                 case HUD_STAT_ALIGN:
3710                 case HUD_STAT_OFFSET:
3711                         writeV2F1000(os, *(v2f *)value);
3712                         break;
3713                 case HUD_STAT_NAME:
3714                 case HUD_STAT_TEXT:
3715                         os << serializeString(*(std::string *)value);
3716                         break;
3717                 case HUD_STAT_NUMBER:
3718                 case HUD_STAT_ITEM:
3719                 case HUD_STAT_DIR:
3720                 default:
3721                         writeU32(os, *(u32 *)value);
3722                         break;
3723         }
3724
3725         // Make data buffer
3726         std::string s = os.str();
3727         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3728         // Send as reliable
3729         m_con.Send(peer_id, 0, data, true);
3730 }
3731
3732 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
3733 {
3734         std::ostringstream os(std::ios_base::binary);
3735
3736         // Write command
3737         writeU16(os, TOCLIENT_HUD_SET_FLAGS);
3738         writeU32(os, flags);
3739         writeU32(os, mask);
3740
3741         // Make data buffer
3742         std::string s = os.str();
3743         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3744         // Send as reliable
3745         m_con.Send(peer_id, 0, data, true);
3746 }
3747
3748 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
3749 {
3750         std::ostringstream os(std::ios_base::binary);
3751
3752         // Write command
3753         writeU16(os, TOCLIENT_HUD_SET_PARAM);
3754         writeU16(os, param);
3755         os<<serializeString(value);
3756
3757         // Make data buffer
3758         std::string s = os.str();
3759         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3760         // Send as reliable
3761         m_con.Send(peer_id, 0, data, true);
3762 }
3763
3764 void Server::BroadcastChatMessage(const std::wstring &message)
3765 {
3766         for(std::map<u16, RemoteClient*>::iterator
3767                 i = m_clients.begin();
3768                 i != m_clients.end(); ++i)
3769         {
3770                 // Get client and check that it is valid
3771                 RemoteClient *client = i->second;
3772                 assert(client->peer_id == i->first);
3773                 if(client->serialization_version == SER_FMT_VER_INVALID)
3774                         continue;
3775
3776                 SendChatMessage(client->peer_id, message);
3777         }
3778 }
3779
3780 void Server::SendPlayerHP(u16 peer_id)
3781 {
3782         DSTACK(__FUNCTION_NAME);
3783         PlayerSAO *playersao = getPlayerSAO(peer_id);
3784         assert(playersao);
3785         playersao->m_hp_not_sent = false;
3786         SendHP(m_con, peer_id, playersao->getHP());
3787 }
3788
3789 void Server::SendPlayerBreath(u16 peer_id)
3790 {
3791         DSTACK(__FUNCTION_NAME);
3792         PlayerSAO *playersao = getPlayerSAO(peer_id);
3793         assert(playersao);
3794         playersao->m_breath_not_sent = false;
3795         SendBreath(m_con, peer_id, playersao->getBreath());
3796 }
3797
3798 void Server::SendMovePlayer(u16 peer_id)
3799 {
3800         DSTACK(__FUNCTION_NAME);
3801         Player *player = m_env->getPlayer(peer_id);
3802         assert(player);
3803
3804         std::ostringstream os(std::ios_base::binary);
3805         writeU16(os, TOCLIENT_MOVE_PLAYER);
3806         writeV3F1000(os, player->getPosition());
3807         writeF1000(os, player->getPitch());
3808         writeF1000(os, player->getYaw());
3809
3810         {
3811                 v3f pos = player->getPosition();
3812                 f32 pitch = player->getPitch();
3813                 f32 yaw = player->getYaw();
3814                 verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
3815                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3816                                 <<" pitch="<<pitch
3817                                 <<" yaw="<<yaw
3818                                 <<std::endl;
3819         }
3820
3821         // Make data buffer
3822         std::string s = os.str();
3823         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3824         // Send as reliable
3825         m_con.Send(peer_id, 0, data, true);
3826 }
3827
3828 void Server::SendPlayerPrivileges(u16 peer_id)
3829 {
3830         Player *player = m_env->getPlayer(peer_id);
3831         assert(player);
3832         if(player->peer_id == PEER_ID_INEXISTENT)
3833                 return;
3834
3835         std::set<std::string> privs;
3836         m_script->getAuth(player->getName(), NULL, &privs);
3837
3838         std::ostringstream os(std::ios_base::binary);
3839         writeU16(os, TOCLIENT_PRIVILEGES);
3840         writeU16(os, privs.size());
3841         for(std::set<std::string>::const_iterator i = privs.begin();
3842                         i != privs.end(); i++){
3843                 os<<serializeString(*i);
3844         }
3845
3846         // Make data buffer
3847         std::string s = os.str();
3848         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3849         // Send as reliable
3850         m_con.Send(peer_id, 0, data, true);
3851 }
3852
3853 void Server::SendPlayerInventoryFormspec(u16 peer_id)
3854 {
3855         Player *player = m_env->getPlayer(peer_id);
3856         assert(player);
3857         if(player->peer_id == PEER_ID_INEXISTENT)
3858                 return;
3859
3860         std::ostringstream os(std::ios_base::binary);
3861         writeU16(os, TOCLIENT_INVENTORY_FORMSPEC);
3862         os<<serializeLongString(player->inventory_formspec);
3863
3864         // Make data buffer
3865         std::string s = os.str();
3866         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3867         // Send as reliable
3868         m_con.Send(peer_id, 0, data, true);
3869 }
3870
3871 s32 Server::playSound(const SimpleSoundSpec &spec,
3872                 const ServerSoundParams &params)
3873 {
3874         // Find out initial position of sound
3875         bool pos_exists = false;
3876         v3f pos = params.getPos(m_env, &pos_exists);
3877         // If position is not found while it should be, cancel sound
3878         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
3879                 return -1;
3880         // Filter destination clients
3881         std::set<RemoteClient*> dst_clients;
3882         if(params.to_player != "")
3883         {
3884                 Player *player = m_env->getPlayer(params.to_player.c_str());
3885                 if(!player){
3886                         infostream<<"Server::playSound: Player \""<<params.to_player
3887                                         <<"\" not found"<<std::endl;
3888                         return -1;
3889                 }
3890                 if(player->peer_id == PEER_ID_INEXISTENT){
3891                         infostream<<"Server::playSound: Player \""<<params.to_player
3892                                         <<"\" not connected"<<std::endl;
3893                         return -1;
3894                 }
3895                 RemoteClient *client = getClient(player->peer_id);
3896                 dst_clients.insert(client);
3897         }
3898         else
3899         {
3900                 for(std::map<u16, RemoteClient*>::iterator
3901                                 i = m_clients.begin(); i != m_clients.end(); ++i)
3902                 {
3903                         RemoteClient *client = i->second;
3904                         Player *player = m_env->getPlayer(client->peer_id);
3905                         if(!player)
3906                                 continue;
3907                         if(pos_exists){
3908                                 if(player->getPosition().getDistanceFrom(pos) >
3909                                                 params.max_hear_distance)
3910                                         continue;
3911                         }
3912                         dst_clients.insert(client);
3913                 }
3914         }
3915         if(dst_clients.size() == 0)
3916                 return -1;
3917         // Create the sound
3918         s32 id = m_next_sound_id++;
3919         // The sound will exist as a reference in m_playing_sounds
3920         m_playing_sounds[id] = ServerPlayingSound();
3921         ServerPlayingSound &psound = m_playing_sounds[id];
3922         psound.params = params;
3923         for(std::set<RemoteClient*>::iterator i = dst_clients.begin();
3924                         i != dst_clients.end(); i++)
3925                 psound.clients.insert((*i)->peer_id);
3926         // Create packet
3927         std::ostringstream os(std::ios_base::binary);
3928         writeU16(os, TOCLIENT_PLAY_SOUND);
3929         writeS32(os, id);
3930         os<<serializeString(spec.name);
3931         writeF1000(os, spec.gain * params.gain);
3932         writeU8(os, params.type);
3933         writeV3F1000(os, pos);
3934         writeU16(os, params.object);
3935         writeU8(os, params.loop);
3936         // Make data buffer
3937         std::string s = os.str();
3938         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3939         // Send
3940         for(std::set<RemoteClient*>::iterator i = dst_clients.begin();
3941                         i != dst_clients.end(); i++){
3942                 // Send as reliable
3943                 m_con.Send((*i)->peer_id, 0, data, true);
3944         }
3945         return id;
3946 }
3947 void Server::stopSound(s32 handle)
3948 {
3949         // Get sound reference
3950         std::map<s32, ServerPlayingSound>::iterator i =
3951                         m_playing_sounds.find(handle);
3952         if(i == m_playing_sounds.end())
3953                 return;
3954         ServerPlayingSound &psound = i->second;
3955         // Create packet
3956         std::ostringstream os(std::ios_base::binary);
3957         writeU16(os, TOCLIENT_STOP_SOUND);
3958         writeS32(os, handle);
3959         // Make data buffer
3960         std::string s = os.str();
3961         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3962         // Send
3963         for(std::set<u16>::iterator i = psound.clients.begin();
3964                         i != psound.clients.end(); i++){
3965                 // Send as reliable
3966                 m_con.Send(*i, 0, data, true);
3967         }
3968         // Remove sound reference
3969         m_playing_sounds.erase(i);
3970 }
3971
3972 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
3973         std::list<u16> *far_players, float far_d_nodes)
3974 {
3975         float maxd = far_d_nodes*BS;
3976         v3f p_f = intToFloat(p, BS);
3977
3978         // Create packet
3979         u32 replysize = 8;
3980         SharedBuffer<u8> reply(replysize);
3981         writeU16(&reply[0], TOCLIENT_REMOVENODE);
3982         writeS16(&reply[2], p.X);
3983         writeS16(&reply[4], p.Y);
3984         writeS16(&reply[6], p.Z);
3985
3986         for(std::map<u16, RemoteClient*>::iterator
3987                 i = m_clients.begin();
3988                 i != m_clients.end(); ++i)
3989         {
3990                 // Get client and check that it is valid
3991                 RemoteClient *client = i->second;
3992                 assert(client->peer_id == i->first);
3993                 if(client->serialization_version == SER_FMT_VER_INVALID)
3994                         continue;
3995
3996                 // Don't send if it's the same one
3997                 if(client->peer_id == ignore_id)
3998                         continue;
3999
4000                 if(far_players)
4001                 {
4002                         // Get player
4003                         Player *player = m_env->getPlayer(client->peer_id);
4004                         if(player)
4005                         {
4006                                 // If player is far away, only set modified blocks not sent
4007                                 v3f player_pos = player->getPosition();
4008                                 if(player_pos.getDistanceFrom(p_f) > maxd)
4009                                 {
4010                                         far_players->push_back(client->peer_id);
4011                                         continue;
4012                                 }
4013                         }
4014                 }
4015
4016                 // Send as reliable
4017                 m_con.Send(client->peer_id, 0, reply, true);
4018         }
4019 }
4020
4021 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
4022                 std::list<u16> *far_players, float far_d_nodes)
4023 {
4024         float maxd = far_d_nodes*BS;
4025         v3f p_f = intToFloat(p, BS);
4026
4027         for(std::map<u16, RemoteClient*>::iterator
4028                 i = m_clients.begin();
4029                 i != m_clients.end(); ++i)
4030         {
4031                 // Get client and check that it is valid
4032                 RemoteClient *client = i->second;
4033                 assert(client->peer_id == i->first);
4034                 if(client->serialization_version == SER_FMT_VER_INVALID)
4035                         continue;
4036
4037                 // Don't send if it's the same one
4038                 if(client->peer_id == ignore_id)
4039                         continue;
4040
4041                 if(far_players)
4042                 {
4043                         // Get player
4044                         Player *player = m_env->getPlayer(client->peer_id);
4045                         if(player)
4046                         {
4047                                 // If player is far away, only set modified blocks not sent
4048                                 v3f player_pos = player->getPosition();
4049                                 if(player_pos.getDistanceFrom(p_f) > maxd)
4050                                 {
4051                                         far_players->push_back(client->peer_id);
4052                                         continue;
4053                                 }
4054                         }
4055                 }
4056
4057                 // Create packet
4058                 u32 replysize = 8 + MapNode::serializedLength(client->serialization_version);
4059                 SharedBuffer<u8> reply(replysize);
4060                 writeU16(&reply[0], TOCLIENT_ADDNODE);
4061                 writeS16(&reply[2], p.X);
4062                 writeS16(&reply[4], p.Y);
4063                 writeS16(&reply[6], p.Z);
4064                 n.serialize(&reply[8], client->serialization_version);
4065
4066                 // Send as reliable
4067                 m_con.Send(client->peer_id, 0, reply, true);
4068         }
4069 }
4070
4071 void Server::setBlockNotSent(v3s16 p)
4072 {
4073         for(std::map<u16, RemoteClient*>::iterator
4074                 i = m_clients.begin();
4075                 i != m_clients.end(); ++i)
4076         {
4077                 RemoteClient *client = i->second;
4078                 client->SetBlockNotSent(p);
4079         }
4080 }
4081
4082 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
4083 {
4084         DSTACK(__FUNCTION_NAME);
4085
4086         v3s16 p = block->getPos();
4087
4088 #if 0
4089         // Analyze it a bit
4090         bool completely_air = true;
4091         for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
4092         for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
4093         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
4094         {
4095                 if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
4096                 {
4097                         completely_air = false;
4098                         x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
4099                 }
4100         }
4101
4102         // Print result
4103         infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
4104         if(completely_air)
4105                 infostream<<"[completely air] ";
4106         infostream<<std::endl;
4107 #endif
4108
4109         /*
4110                 Create a packet with the block in the right format
4111         */
4112
4113         std::ostringstream os(std::ios_base::binary);
4114         block->serialize(os, ver, false);
4115         block->serializeNetworkSpecific(os, net_proto_version);
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, client->net_proto_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