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