]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Lua HUD
[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 void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec, const std::string formname)
3453 {
3454         DSTACK(__FUNCTION_NAME);
3455
3456         std::ostringstream os(std::ios_base::binary);
3457         u8 buf[12];
3458
3459         // Write command
3460         writeU16(buf, TOCLIENT_SHOW_FORMSPEC);
3461         os.write((char*)buf, 2);
3462         os<<serializeLongString(formspec);
3463         os<<serializeString(formname);
3464
3465         // Make data buffer
3466         std::string s = os.str();
3467         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3468         // Send as reliable
3469         m_con.Send(peer_id, 0, data, true);
3470 }
3471
3472 // Spawns a particle on peer with peer_id
3473 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, bool collisiondetection, std::string texture)
3474 {
3475         DSTACK(__FUNCTION_NAME);
3476
3477         std::ostringstream os(std::ios_base::binary);
3478         writeU16(os, TOCLIENT_SPAWN_PARTICLE);
3479         writeV3F1000(os, pos);
3480         writeV3F1000(os, velocity);
3481         writeV3F1000(os, acceleration);
3482         writeF1000(os, expirationtime);
3483         writeF1000(os, size);
3484         writeU8(os,  collisiondetection);
3485         os<<serializeLongString(texture);
3486
3487         // Make data buffer
3488         std::string s = os.str();
3489         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3490         // Send as reliable
3491         m_con.Send(peer_id, 0, data, true);
3492 }
3493
3494 // Spawns a particle on all peers
3495 void Server::SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, bool collisiondetection, std::string texture)
3496 {
3497         for(std::map<u16, RemoteClient*>::iterator
3498                 i = m_clients.begin();
3499                 i != m_clients.end(); i++)
3500         {
3501                 // Get client and check that it is valid
3502                 RemoteClient *client = i->second;
3503                 assert(client->peer_id == i->first);
3504                 if(client->serialization_version == SER_FMT_VER_INVALID)
3505                         continue;
3506
3507                 SendSpawnParticle(client->peer_id, pos, velocity, acceleration,
3508                         expirationtime, size, collisiondetection, texture);
3509         }
3510 }
3511
3512 // Adds a ParticleSpawner on peer with peer_id
3513 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
3514         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3515         float minsize, float maxsize, bool collisiondetection, std::string texture, u32 id)
3516 {
3517         DSTACK(__FUNCTION_NAME);
3518
3519         std::ostringstream os(std::ios_base::binary);
3520         writeU16(os, TOCLIENT_ADD_PARTICLESPAWNER);
3521
3522         writeU16(os, amount);
3523         writeF1000(os, spawntime);
3524         writeV3F1000(os, minpos);
3525         writeV3F1000(os, maxpos);
3526         writeV3F1000(os, minvel);
3527         writeV3F1000(os, maxvel);
3528         writeV3F1000(os, minacc);
3529         writeV3F1000(os, maxacc);
3530         writeF1000(os, minexptime);
3531         writeF1000(os, maxexptime);
3532         writeF1000(os, minsize);
3533         writeF1000(os, maxsize);
3534         writeU8(os,  collisiondetection);
3535         os<<serializeLongString(texture);
3536         writeU32(os, id);
3537
3538         // Make data buffer
3539         std::string s = os.str();
3540         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3541         // Send as reliable
3542         m_con.Send(peer_id, 0, data, true);
3543 }
3544
3545 // Adds a ParticleSpawner on all peers
3546 void Server::SendAddParticleSpawnerAll(u16 amount, float spawntime, v3f minpos, v3f maxpos,
3547         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3548         float minsize, float maxsize, bool collisiondetection, std::string texture, u32 id)
3549 {
3550         for(std::map<u16, RemoteClient*>::iterator
3551                 i = m_clients.begin();
3552                 i != m_clients.end(); i++)
3553         {
3554                 // Get client and check that it is valid
3555                 RemoteClient *client = i->second;
3556                 assert(client->peer_id == i->first);
3557                 if(client->serialization_version == SER_FMT_VER_INVALID)
3558                         continue;
3559
3560                 SendAddParticleSpawner(client->peer_id, amount, spawntime,
3561                         minpos, maxpos, minvel, maxvel, minacc, maxacc,
3562                         minexptime, maxexptime, minsize, maxsize, collisiondetection, texture, id);
3563         }
3564 }
3565
3566 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
3567 {
3568         DSTACK(__FUNCTION_NAME);
3569
3570         std::ostringstream os(std::ios_base::binary);
3571         writeU16(os, TOCLIENT_DELETE_PARTICLESPAWNER);
3572
3573         writeU16(os, id);
3574
3575         // Make data buffer
3576         std::string s = os.str();
3577         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3578         // Send as reliable
3579         m_con.Send(peer_id, 0, data, true);
3580 }
3581
3582 void Server::SendDeleteParticleSpawnerAll(u32 id)
3583 {
3584         for(std::map<u16, RemoteClient*>::iterator
3585                 i = m_clients.begin();
3586                 i != m_clients.end(); i++)
3587         {
3588                 // Get client and check that it is valid
3589                 RemoteClient *client = i->second;
3590                 assert(client->peer_id == i->first);
3591                 if(client->serialization_version == SER_FMT_VER_INVALID)
3592                         continue;
3593
3594                 SendDeleteParticleSpawner(client->peer_id, id);
3595         }
3596 }
3597
3598 void Server::SendHUDAdd(u16 peer_id, const u32 id, HudElement* form)
3599 {
3600         DSTACK(__FUNCTION_NAME);
3601
3602         std::ostringstream os(std::ios_base::binary);
3603         u8 buf[12];
3604
3605         // Write command
3606         writeU16(buf, TOCLIENT_HUDADD);
3607         os.write((char*)buf, 2);
3608         writeU32(os, id);
3609         writeU8(os, form->type);
3610         writeV2F1000(os, form->pos);
3611         os<<serializeString(form->name);
3612         writeV2F1000(os, form->scale);
3613         os<<serializeString(form->text);
3614         writeU32(os, form->number);
3615         writeU32(os, form->item);
3616         writeU32(os, form->dir);
3617
3618         // Make data buffer
3619         std::string s = os.str();
3620         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3621         // Send as reliable
3622         m_con.Send(peer_id, 0, data, true);
3623 }
3624
3625 void Server::SendHUDRm(u16 peer_id, const u32 id)
3626 {
3627         DSTACK(__FUNCTION_NAME);
3628
3629         std::ostringstream os(std::ios_base::binary);
3630         u8 buf[12];
3631
3632         // Write command
3633         writeU16(buf, TOCLIENT_HUDRM);
3634         os.write((char*)buf, 2);
3635         writeU32(os, id);
3636
3637         // Make data buffer
3638         std::string s = os.str();
3639         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3640         // Send as reliable
3641         m_con.Send(peer_id, 0, data, true);
3642 }
3643
3644 void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, v2f data)
3645 {
3646         DSTACK(__FUNCTION_NAME);
3647
3648         std::ostringstream os(std::ios_base::binary);
3649         u8 buf[12];
3650
3651         // Write command
3652         writeU16(buf, TOCLIENT_HUDCHANGE);
3653         os.write((char*)buf, 2);
3654         writeU32(os, id);
3655         writeU8(os, stat);
3656         writeV2F1000(os, data);
3657
3658         // Make data buffer
3659         std::string s = os.str();
3660         SharedBuffer<u8> ddata((u8*)s.c_str(), s.size());
3661         // Send as reliable
3662         m_con.Send(peer_id, 0, ddata, true);
3663 }
3664
3665 void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, std::string data)
3666 {
3667         DSTACK(__FUNCTION_NAME);
3668
3669         std::ostringstream os(std::ios_base::binary);
3670         u8 buf[12];
3671
3672         // Write command
3673         writeU16(buf, TOCLIENT_HUDCHANGE);
3674         os.write((char*)buf, 2);
3675         writeU32(os, id);
3676         writeU8(os, stat);
3677         os<<serializeString(data);
3678
3679         // Make data buffer
3680         std::string s = os.str();
3681         SharedBuffer<u8> ddata((u8*)s.c_str(), s.size());
3682         // Send as reliable
3683         m_con.Send(peer_id, 0, ddata, true);
3684 }
3685
3686 void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, u32 data)
3687 {
3688         DSTACK(__FUNCTION_NAME);
3689
3690         std::ostringstream os(std::ios_base::binary);
3691         u8 buf[12];
3692
3693         // Write command
3694         writeU16(buf, TOCLIENT_HUDCHANGE);
3695         os.write((char*)buf, 2);
3696         writeU32(os, id);
3697         writeU8(os, stat);
3698         writeU32(os, data);
3699
3700         // Make data buffer
3701         std::string s = os.str();
3702         SharedBuffer<u8> ddata((u8*)s.c_str(), s.size());
3703         // Send as reliable
3704         m_con.Send(peer_id, 0, ddata, true);
3705 }
3706
3707 void Server::BroadcastChatMessage(const std::wstring &message)
3708 {
3709         for(std::map<u16, RemoteClient*>::iterator
3710                 i = m_clients.begin();
3711                 i != m_clients.end(); ++i)
3712         {
3713                 // Get client and check that it is valid
3714                 RemoteClient *client = i->second;
3715                 assert(client->peer_id == i->first);
3716                 if(client->serialization_version == SER_FMT_VER_INVALID)
3717                         continue;
3718
3719                 SendChatMessage(client->peer_id, message);
3720         }
3721 }
3722
3723 void Server::SendPlayerHP(u16 peer_id)
3724 {
3725         DSTACK(__FUNCTION_NAME);
3726         PlayerSAO *playersao = getPlayerSAO(peer_id);
3727         assert(playersao);
3728         playersao->m_hp_not_sent = false;
3729         SendHP(m_con, peer_id, playersao->getHP());
3730 }
3731
3732 void Server::SendMovePlayer(u16 peer_id)
3733 {
3734         DSTACK(__FUNCTION_NAME);
3735         Player *player = m_env->getPlayer(peer_id);
3736         assert(player);
3737
3738         std::ostringstream os(std::ios_base::binary);
3739         writeU16(os, TOCLIENT_MOVE_PLAYER);
3740         writeV3F1000(os, player->getPosition());
3741         writeF1000(os, player->getPitch());
3742         writeF1000(os, player->getYaw());
3743
3744         {
3745                 v3f pos = player->getPosition();
3746                 f32 pitch = player->getPitch();
3747                 f32 yaw = player->getYaw();
3748                 verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
3749                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3750                                 <<" pitch="<<pitch
3751                                 <<" yaw="<<yaw
3752                                 <<std::endl;
3753         }
3754
3755         // Make data buffer
3756         std::string s = os.str();
3757         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3758         // Send as reliable
3759         m_con.Send(peer_id, 0, data, true);
3760 }
3761
3762 void Server::SendPlayerPrivileges(u16 peer_id)
3763 {
3764         Player *player = m_env->getPlayer(peer_id);
3765         assert(player);
3766         if(player->peer_id == PEER_ID_INEXISTENT)
3767                 return;
3768
3769         std::set<std::string> privs;
3770         scriptapi_get_auth(m_lua, player->getName(), NULL, &privs);
3771
3772         std::ostringstream os(std::ios_base::binary);
3773         writeU16(os, TOCLIENT_PRIVILEGES);
3774         writeU16(os, privs.size());
3775         for(std::set<std::string>::const_iterator i = privs.begin();
3776                         i != privs.end(); i++){
3777                 os<<serializeString(*i);
3778         }
3779
3780         // Make data buffer
3781         std::string s = os.str();
3782         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3783         // Send as reliable
3784         m_con.Send(peer_id, 0, data, true);
3785 }
3786
3787 void Server::SendPlayerInventoryFormspec(u16 peer_id)
3788 {
3789         Player *player = m_env->getPlayer(peer_id);
3790         assert(player);
3791         if(player->peer_id == PEER_ID_INEXISTENT)
3792                 return;
3793
3794         std::ostringstream os(std::ios_base::binary);
3795         writeU16(os, TOCLIENT_INVENTORY_FORMSPEC);
3796         os<<serializeLongString(player->inventory_formspec);
3797
3798         // Make data buffer
3799         std::string s = os.str();
3800         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3801         // Send as reliable
3802         m_con.Send(peer_id, 0, data, true);
3803 }
3804
3805 s32 Server::playSound(const SimpleSoundSpec &spec,
3806                 const ServerSoundParams &params)
3807 {
3808         // Find out initial position of sound
3809         bool pos_exists = false;
3810         v3f pos = params.getPos(m_env, &pos_exists);
3811         // If position is not found while it should be, cancel sound
3812         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
3813                 return -1;
3814         // Filter destination clients
3815         std::set<RemoteClient*> dst_clients;
3816         if(params.to_player != "")
3817         {
3818                 Player *player = m_env->getPlayer(params.to_player.c_str());
3819                 if(!player){
3820                         infostream<<"Server::playSound: Player \""<<params.to_player
3821                                         <<"\" not found"<<std::endl;
3822                         return -1;
3823                 }
3824                 if(player->peer_id == PEER_ID_INEXISTENT){
3825                         infostream<<"Server::playSound: Player \""<<params.to_player
3826                                         <<"\" not connected"<<std::endl;
3827                         return -1;
3828                 }
3829                 RemoteClient *client = getClient(player->peer_id);
3830                 dst_clients.insert(client);
3831         }
3832         else
3833         {
3834                 for(std::map<u16, RemoteClient*>::iterator
3835                                 i = m_clients.begin(); i != m_clients.end(); ++i)
3836                 {
3837                         RemoteClient *client = i->second;
3838                         Player *player = m_env->getPlayer(client->peer_id);
3839                         if(!player)
3840                                 continue;
3841                         if(pos_exists){
3842                                 if(player->getPosition().getDistanceFrom(pos) >
3843                                                 params.max_hear_distance)
3844                                         continue;
3845                         }
3846                         dst_clients.insert(client);
3847                 }
3848         }
3849         if(dst_clients.size() == 0)
3850                 return -1;
3851         // Create the sound
3852         s32 id = m_next_sound_id++;
3853         // The sound will exist as a reference in m_playing_sounds
3854         m_playing_sounds[id] = ServerPlayingSound();
3855         ServerPlayingSound &psound = m_playing_sounds[id];
3856         psound.params = params;
3857         for(std::set<RemoteClient*>::iterator i = dst_clients.begin();
3858                         i != dst_clients.end(); i++)
3859                 psound.clients.insert((*i)->peer_id);
3860         // Create packet
3861         std::ostringstream os(std::ios_base::binary);
3862         writeU16(os, TOCLIENT_PLAY_SOUND);
3863         writeS32(os, id);
3864         os<<serializeString(spec.name);
3865         writeF1000(os, spec.gain * params.gain);
3866         writeU8(os, params.type);
3867         writeV3F1000(os, pos);
3868         writeU16(os, params.object);
3869         writeU8(os, params.loop);
3870         // Make data buffer
3871         std::string s = os.str();
3872         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3873         // Send
3874         for(std::set<RemoteClient*>::iterator i = dst_clients.begin();
3875                         i != dst_clients.end(); i++){
3876                 // Send as reliable
3877                 m_con.Send((*i)->peer_id, 0, data, true);
3878         }
3879         return id;
3880 }
3881 void Server::stopSound(s32 handle)
3882 {
3883         // Get sound reference
3884         std::map<s32, ServerPlayingSound>::iterator i =
3885                         m_playing_sounds.find(handle);
3886         if(i == m_playing_sounds.end())
3887                 return;
3888         ServerPlayingSound &psound = i->second;
3889         // Create packet
3890         std::ostringstream os(std::ios_base::binary);
3891         writeU16(os, TOCLIENT_STOP_SOUND);
3892         writeS32(os, handle);
3893         // Make data buffer
3894         std::string s = os.str();
3895         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3896         // Send
3897         for(std::set<u16>::iterator i = psound.clients.begin();
3898                         i != psound.clients.end(); i++){
3899                 // Send as reliable
3900                 m_con.Send(*i, 0, data, true);
3901         }
3902         // Remove sound reference
3903         m_playing_sounds.erase(i);
3904 }
3905
3906 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
3907         std::list<u16> *far_players, float far_d_nodes)
3908 {
3909         float maxd = far_d_nodes*BS;
3910         v3f p_f = intToFloat(p, BS);
3911
3912         // Create packet
3913         u32 replysize = 8;
3914         SharedBuffer<u8> reply(replysize);
3915         writeU16(&reply[0], TOCLIENT_REMOVENODE);
3916         writeS16(&reply[2], p.X);
3917         writeS16(&reply[4], p.Y);
3918         writeS16(&reply[6], p.Z);
3919
3920         for(std::map<u16, RemoteClient*>::iterator
3921                 i = m_clients.begin();
3922                 i != m_clients.end(); ++i)
3923         {
3924                 // Get client and check that it is valid
3925                 RemoteClient *client = i->second;
3926                 assert(client->peer_id == i->first);
3927                 if(client->serialization_version == SER_FMT_VER_INVALID)
3928                         continue;
3929
3930                 // Don't send if it's the same one
3931                 if(client->peer_id == ignore_id)
3932                         continue;
3933
3934                 if(far_players)
3935                 {
3936                         // Get player
3937                         Player *player = m_env->getPlayer(client->peer_id);
3938                         if(player)
3939                         {
3940                                 // If player is far away, only set modified blocks not sent
3941                                 v3f player_pos = player->getPosition();
3942                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3943                                 {
3944                                         far_players->push_back(client->peer_id);
3945                                         continue;
3946                                 }
3947                         }
3948                 }
3949
3950                 // Send as reliable
3951                 m_con.Send(client->peer_id, 0, reply, true);
3952         }
3953 }
3954
3955 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
3956                 std::list<u16> *far_players, float far_d_nodes)
3957 {
3958         float maxd = far_d_nodes*BS;
3959         v3f p_f = intToFloat(p, BS);
3960
3961         for(std::map<u16, RemoteClient*>::iterator
3962                 i = m_clients.begin();
3963                 i != m_clients.end(); ++i)
3964         {
3965                 // Get client and check that it is valid
3966                 RemoteClient *client = i->second;
3967                 assert(client->peer_id == i->first);
3968                 if(client->serialization_version == SER_FMT_VER_INVALID)
3969                         continue;
3970
3971                 // Don't send if it's the same one
3972                 if(client->peer_id == ignore_id)
3973                         continue;
3974
3975                 if(far_players)
3976                 {
3977                         // Get player
3978                         Player *player = m_env->getPlayer(client->peer_id);
3979                         if(player)
3980                         {
3981                                 // If player is far away, only set modified blocks not sent
3982                                 v3f player_pos = player->getPosition();
3983                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3984                                 {
3985                                         far_players->push_back(client->peer_id);
3986                                         continue;
3987                                 }
3988                         }
3989                 }
3990
3991                 // Create packet
3992                 u32 replysize = 8 + MapNode::serializedLength(client->serialization_version);
3993                 SharedBuffer<u8> reply(replysize);
3994                 writeU16(&reply[0], TOCLIENT_ADDNODE);
3995                 writeS16(&reply[2], p.X);
3996                 writeS16(&reply[4], p.Y);
3997                 writeS16(&reply[6], p.Z);
3998                 n.serialize(&reply[8], client->serialization_version);
3999
4000                 // Send as reliable
4001                 m_con.Send(client->peer_id, 0, reply, true);
4002         }
4003 }
4004
4005 void Server::setBlockNotSent(v3s16 p)
4006 {
4007         for(std::map<u16, RemoteClient*>::iterator
4008                 i = m_clients.begin();
4009                 i != m_clients.end(); ++i)
4010         {
4011                 RemoteClient *client = i->second;
4012                 client->SetBlockNotSent(p);
4013         }
4014 }
4015
4016 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
4017 {
4018         DSTACK(__FUNCTION_NAME);
4019
4020         v3s16 p = block->getPos();
4021
4022 #if 0
4023         // Analyze it a bit
4024         bool completely_air = true;
4025         for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
4026         for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
4027         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
4028         {
4029                 if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
4030                 {
4031                         completely_air = false;
4032                         x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
4033                 }
4034         }
4035
4036         // Print result
4037         infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
4038         if(completely_air)
4039                 infostream<<"[completely air] ";
4040         infostream<<std::endl;
4041 #endif
4042
4043         /*
4044                 Create a packet with the block in the right format
4045         */
4046
4047         std::ostringstream os(std::ios_base::binary);
4048         block->serialize(os, ver, false);
4049         std::string s = os.str();
4050         SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
4051
4052         u32 replysize = 8 + blockdata.getSize();
4053         SharedBuffer<u8> reply(replysize);
4054         writeU16(&reply[0], TOCLIENT_BLOCKDATA);
4055         writeS16(&reply[2], p.X);
4056         writeS16(&reply[4], p.Y);
4057         writeS16(&reply[6], p.Z);
4058         memcpy(&reply[8], *blockdata, blockdata.getSize());
4059
4060         /*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
4061                         <<":  \tpacket size: "<<replysize<<std::endl;*/
4062
4063         /*
4064                 Send packet
4065         */
4066         m_con.Send(peer_id, 1, reply, true);
4067 }
4068
4069 void Server::SendBlocks(float dtime)
4070 {
4071         DSTACK(__FUNCTION_NAME);
4072
4073         JMutexAutoLock envlock(m_env_mutex);
4074         JMutexAutoLock conlock(m_con_mutex);
4075
4076         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
4077
4078         std::vector<PrioritySortedBlockTransfer> queue;
4079
4080         s32 total_sending = 0;
4081
4082         {
4083                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
4084
4085                 for(std::map<u16, RemoteClient*>::iterator
4086                         i = m_clients.begin();
4087                         i != m_clients.end(); ++i)
4088                 {
4089                         RemoteClient *client = i->second;
4090                         assert(client->peer_id == i->first);
4091
4092                         // If definitions and textures have not been sent, don't
4093                         // send MapBlocks either
4094                         if(!client->definitions_sent)
4095                                 continue;
4096
4097                         total_sending += client->SendingCount();
4098
4099                         if(client->serialization_version == SER_FMT_VER_INVALID)
4100                                 continue;
4101
4102                         client->GetNextBlocks(this, dtime, queue);
4103                 }
4104         }
4105
4106         // Sort.
4107         // Lowest priority number comes first.
4108         // Lowest is most important.
4109         std::sort(queue.begin(), queue.end());
4110
4111         for(u32 i=0; i<queue.size(); i++)
4112         {
4113                 //TODO: Calculate limit dynamically
4114                 if(total_sending >= g_settings->getS32
4115                                 ("max_simultaneous_block_sends_server_total"))
4116                         break;
4117
4118                 PrioritySortedBlockTransfer q = queue[i];
4119
4120                 MapBlock *block = NULL;
4121                 try
4122                 {
4123                         block = m_env->getMap().getBlockNoCreate(q.pos);
4124                 }
4125                 catch(InvalidPositionException &e)
4126                 {
4127                         continue;
4128                 }
4129
4130                 RemoteClient *client = getClient(q.peer_id);
4131
4132                 SendBlockNoLock(q.peer_id, block, client->serialization_version);
4133
4134                 client->SentBlock(q.pos);
4135
4136                 total_sending++;
4137         }
4138 }
4139
4140 void Server::fillMediaCache()
4141 {
4142         DSTACK(__FUNCTION_NAME);
4143
4144         infostream<<"Server: Calculating media file checksums"<<std::endl;
4145
4146         // Collect all media file paths
4147         std::list<std::string> paths;
4148         for(std::vector<ModSpec>::iterator i = m_mods.begin();
4149                         i != m_mods.end(); i++){
4150                 const ModSpec &mod = *i;
4151                 paths.push_back(mod.path + DIR_DELIM + "textures");
4152                 paths.push_back(mod.path + DIR_DELIM + "sounds");
4153                 paths.push_back(mod.path + DIR_DELIM + "media");
4154                 paths.push_back(mod.path + DIR_DELIM + "models");
4155         }
4156         std::string path_all = "textures";
4157         paths.push_back(path_all + DIR_DELIM + "all");
4158
4159         // Collect media file information from paths into cache
4160         for(std::list<std::string>::iterator i = paths.begin();
4161                         i != paths.end(); i++)
4162         {
4163                 std::string mediapath = *i;
4164                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
4165                 for(u32 j=0; j<dirlist.size(); j++){
4166                         if(dirlist[j].dir) // Ignode dirs
4167                                 continue;
4168                         std::string filename = dirlist[j].name;
4169                         // If name contains illegal characters, ignore the file
4170                         if(!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)){
4171                                 infostream<<"Server: ignoring illegal file name: \""
4172                                                 <<filename<<"\""<<std::endl;
4173                                 continue;
4174                         }
4175                         // If name is not in a supported format, ignore it
4176                         const char *supported_ext[] = {
4177                                 ".png", ".jpg", ".bmp", ".tga",
4178                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
4179                                 ".ogg",
4180                                 ".x", ".b3d", ".md2", ".obj",
4181                                 NULL
4182                         };
4183                         if(removeStringEnd(filename, supported_ext) == ""){
4184                                 infostream<<"Server: ignoring unsupported file extension: \""
4185                                                 <<filename<<"\""<<std::endl;
4186                                 continue;
4187                         }
4188                         // Ok, attempt to load the file and add to cache
4189                         std::string filepath = mediapath + DIR_DELIM + filename;
4190                         // Read data
4191                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
4192                         if(fis.good() == false){
4193                                 errorstream<<"Server::fillMediaCache(): Could not open \""
4194                                                 <<filename<<"\" for reading"<<std::endl;
4195                                 continue;
4196                         }
4197                         std::ostringstream tmp_os(std::ios_base::binary);
4198                         bool bad = false;
4199                         for(;;){
4200                                 char buf[1024];
4201                                 fis.read(buf, 1024);
4202                                 std::streamsize len = fis.gcount();
4203                                 tmp_os.write(buf, len);
4204                                 if(fis.eof())
4205                                         break;
4206                                 if(!fis.good()){
4207                                         bad = true;
4208                                         break;
4209                                 }
4210                         }
4211                         if(bad){
4212                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
4213                                                 <<filename<<"\""<<std::endl;
4214                                 continue;
4215                         }
4216                         if(tmp_os.str().length() == 0){
4217                                 errorstream<<"Server::fillMediaCache(): Empty file \""
4218                                                 <<filepath<<"\""<<std::endl;
4219                                 continue;
4220                         }
4221
4222                         SHA1 sha1;
4223                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
4224
4225                         unsigned char *digest = sha1.getDigest();
4226                         std::string sha1_base64 = base64_encode(digest, 20);
4227                         std::string sha1_hex = hex_encode((char*)digest, 20);
4228                         free(digest);
4229
4230                         // Put in list
4231                         this->m_media[filename] = MediaInfo(filepath, sha1_base64);
4232                         verbosestream<<"Server: "<<sha1_hex<<" is "<<filename<<std::endl;
4233                 }
4234         }
4235 }
4236
4237 struct SendableMediaAnnouncement
4238 {
4239         std::string name;
4240         std::string sha1_digest;
4241
4242         SendableMediaAnnouncement(const std::string name_="",
4243                         const std::string sha1_digest_=""):
4244                 name(name_),
4245                 sha1_digest(sha1_digest_)
4246         {}
4247 };
4248
4249 void Server::sendMediaAnnouncement(u16 peer_id)
4250 {
4251         DSTACK(__FUNCTION_NAME);
4252
4253         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
4254                         <<std::endl;
4255
4256         std::list<SendableMediaAnnouncement> file_announcements;
4257
4258         for(std::map<std::string, MediaInfo>::iterator i = m_media.begin();
4259                         i != m_media.end(); i++){
4260                 // Put in list
4261                 file_announcements.push_back(
4262                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
4263         }
4264
4265         // Make packet
4266         std::ostringstream os(std::ios_base::binary);
4267
4268         /*
4269                 u16 command
4270                 u32 number of files
4271                 for each texture {
4272                         u16 length of name
4273                         string name
4274                         u16 length of sha1_digest
4275                         string sha1_digest
4276                 }
4277         */
4278
4279         writeU16(os, TOCLIENT_ANNOUNCE_MEDIA);
4280         writeU16(os, file_announcements.size());
4281
4282         for(std::list<SendableMediaAnnouncement>::iterator
4283                         j = file_announcements.begin();
4284                         j != file_announcements.end(); ++j){
4285                 os<<serializeString(j->name);
4286                 os<<serializeString(j->sha1_digest);
4287         }
4288         os<<serializeString(g_settings->get("remote_media"));
4289
4290         // Make data buffer
4291         std::string s = os.str();
4292         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4293
4294         // Send as reliable
4295         m_con.Send(peer_id, 0, data, true);
4296 }
4297
4298 struct SendableMedia
4299 {
4300         std::string name;
4301         std::string path;
4302         std::string data;
4303
4304         SendableMedia(const std::string &name_="", const std::string path_="",
4305                         const std::string &data_=""):
4306                 name(name_),
4307                 path(path_),
4308                 data(data_)
4309         {}
4310 };
4311
4312 void Server::sendRequestedMedia(u16 peer_id,
4313                 const std::list<MediaRequest> &tosend)
4314 {
4315         DSTACK(__FUNCTION_NAME);
4316
4317         verbosestream<<"Server::sendRequestedMedia(): "
4318                         <<"Sending files to client"<<std::endl;
4319
4320         /* Read files */
4321
4322         // Put 5kB in one bunch (this is not accurate)
4323         u32 bytes_per_bunch = 5000;
4324
4325         std::vector< std::list<SendableMedia> > file_bunches;
4326         file_bunches.push_back(std::list<SendableMedia>());
4327
4328         u32 file_size_bunch_total = 0;
4329
4330         for(std::list<MediaRequest>::const_iterator i = tosend.begin();
4331                         i != tosend.end(); ++i)
4332         {
4333                 if(m_media.find(i->name) == m_media.end()){
4334                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
4335                                         <<"unknown file \""<<(i->name)<<"\""<<std::endl;
4336                         continue;
4337                 }
4338
4339                 //TODO get path + name
4340                 std::string tpath = m_media[(*i).name].path;
4341
4342                 // Read data
4343                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
4344                 if(fis.good() == false){
4345                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
4346                                         <<tpath<<"\" for reading"<<std::endl;
4347                         continue;
4348                 }
4349                 std::ostringstream tmp_os(std::ios_base::binary);
4350                 bool bad = false;
4351                 for(;;){
4352                         char buf[1024];
4353                         fis.read(buf, 1024);
4354                         std::streamsize len = fis.gcount();
4355                         tmp_os.write(buf, len);
4356                         file_size_bunch_total += len;
4357                         if(fis.eof())
4358                                 break;
4359                         if(!fis.good()){
4360                                 bad = true;
4361                                 break;
4362                         }
4363                 }
4364                 if(bad){
4365                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
4366                                         <<(*i).name<<"\""<<std::endl;
4367                         continue;
4368                 }
4369                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
4370                                 <<tname<<"\""<<std::endl;*/
4371                 // Put in list
4372                 file_bunches[file_bunches.size()-1].push_back(
4373                                 SendableMedia((*i).name, tpath, tmp_os.str()));
4374
4375                 // Start next bunch if got enough data
4376                 if(file_size_bunch_total >= bytes_per_bunch){
4377                         file_bunches.push_back(std::list<SendableMedia>());
4378                         file_size_bunch_total = 0;
4379                 }
4380
4381         }
4382
4383         /* Create and send packets */
4384
4385         u32 num_bunches = file_bunches.size();
4386         for(u32 i=0; i<num_bunches; i++)
4387         {
4388                 std::ostringstream os(std::ios_base::binary);
4389
4390                 /*
4391                         u16 command
4392                         u16 total number of texture bunches
4393                         u16 index of this bunch
4394                         u32 number of files in this bunch
4395                         for each file {
4396                                 u16 length of name
4397                                 string name
4398                                 u32 length of data
4399                                 data
4400                         }
4401                 */
4402
4403                 writeU16(os, TOCLIENT_MEDIA);
4404                 writeU16(os, num_bunches);
4405                 writeU16(os, i);
4406                 writeU32(os, file_bunches[i].size());
4407
4408                 for(std::list<SendableMedia>::iterator
4409                                 j = file_bunches[i].begin();
4410                                 j != file_bunches[i].end(); ++j){
4411                         os<<serializeString(j->name);
4412                         os<<serializeLongString(j->data);
4413                 }
4414
4415                 // Make data buffer
4416                 std::string s = os.str();
4417                 verbosestream<<"Server::sendRequestedMedia(): bunch "
4418                                 <<i<<"/"<<num_bunches
4419                                 <<" files="<<file_bunches[i].size()
4420                                 <<" size=" <<s.size()<<std::endl;
4421                 SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4422                 // Send as reliable
4423                 m_con.Send(peer_id, 0, data, true);
4424         }
4425 }
4426
4427 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
4428 {
4429         if(m_detached_inventories.count(name) == 0){
4430                 errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
4431                 return;
4432         }
4433         Inventory *inv = m_detached_inventories[name];
4434
4435         std::ostringstream os(std::ios_base::binary);
4436         writeU16(os, TOCLIENT_DETACHED_INVENTORY);
4437         os<<serializeString(name);
4438         inv->serialize(os);
4439
4440         // Make data buffer
4441         std::string s = os.str();
4442         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4443         // Send as reliable
4444         m_con.Send(peer_id, 0, data, true);
4445 }
4446
4447 void Server::sendDetachedInventoryToAll(const std::string &name)
4448 {
4449         DSTACK(__FUNCTION_NAME);
4450
4451         for(std::map<u16, RemoteClient*>::iterator
4452                         i = m_clients.begin();
4453                         i != m_clients.end(); ++i){
4454                 RemoteClient *client = i->second;
4455                 sendDetachedInventory(name, client->peer_id);
4456         }
4457 }
4458
4459 void Server::sendDetachedInventories(u16 peer_id)
4460 {
4461         DSTACK(__FUNCTION_NAME);
4462
4463         for(std::map<std::string, Inventory*>::iterator
4464                         i = m_detached_inventories.begin();
4465                         i != m_detached_inventories.end(); i++){
4466                 const std::string &name = i->first;
4467                 //Inventory *inv = i->second;
4468                 sendDetachedInventory(name, peer_id);
4469         }
4470 }
4471
4472 /*
4473         Something random
4474 */
4475
4476 void Server::DiePlayer(u16 peer_id)
4477 {
4478         DSTACK(__FUNCTION_NAME);
4479
4480         PlayerSAO *playersao = getPlayerSAO(peer_id);
4481         assert(playersao);
4482
4483         infostream<<"Server::DiePlayer(): Player "
4484                         <<playersao->getPlayer()->getName()
4485                         <<" dies"<<std::endl;
4486
4487         playersao->setHP(0);
4488
4489         // Trigger scripted stuff
4490         scriptapi_on_dieplayer(m_lua, playersao);
4491
4492         SendPlayerHP(peer_id);
4493         SendDeathscreen(m_con, peer_id, false, v3f(0,0,0));
4494 }
4495
4496 void Server::RespawnPlayer(u16 peer_id)
4497 {
4498         DSTACK(__FUNCTION_NAME);
4499
4500         PlayerSAO *playersao = getPlayerSAO(peer_id);
4501         assert(playersao);
4502
4503         infostream<<"Server::RespawnPlayer(): Player "
4504                         <<playersao->getPlayer()->getName()
4505                         <<" respawns"<<std::endl;
4506
4507         playersao->setHP(PLAYER_MAX_HP);
4508
4509         bool repositioned = scriptapi_on_respawnplayer(m_lua, playersao);
4510         if(!repositioned){
4511                 v3f pos = findSpawnPos(m_env->getServerMap());
4512                 playersao->setPos(pos);
4513         }
4514 }
4515
4516 void Server::UpdateCrafting(u16 peer_id)
4517 {
4518         DSTACK(__FUNCTION_NAME);
4519
4520         Player* player = m_env->getPlayer(peer_id);
4521         assert(player);
4522
4523         // Get a preview for crafting
4524         ItemStack preview;
4525         getCraftingResult(&player->inventory, preview, false, this);
4526
4527         // Put the new preview in
4528         InventoryList *plist = player->inventory.getList("craftpreview");
4529         assert(plist);
4530         assert(plist->getSize() >= 1);
4531         plist->changeItem(0, preview);
4532 }
4533
4534 RemoteClient* Server::getClient(u16 peer_id)
4535 {
4536         DSTACK(__FUNCTION_NAME);
4537         //JMutexAutoLock lock(m_con_mutex);
4538         std::map<u16, RemoteClient*>::iterator n;
4539         n = m_clients.find(peer_id);
4540         // A client should exist for all peers
4541         assert(n != m_clients.end());
4542         return n->second;
4543 }
4544
4545 std::wstring Server::getStatusString()
4546 {
4547         std::wostringstream os(std::ios_base::binary);
4548         os<<L"# Server: ";
4549         // Version
4550         os<<L"version="<<narrow_to_wide(VERSION_STRING);
4551         // Uptime
4552         os<<L", uptime="<<m_uptime.get();
4553         // Information about clients
4554         std::map<u16, RemoteClient*>::iterator i;
4555         bool first;
4556         os<<L", clients={";
4557         for(i = m_clients.begin(), first = true;
4558                 i != m_clients.end(); ++i)
4559         {
4560                 // Get client and check that it is valid
4561                 RemoteClient *client = i->second;
4562                 assert(client->peer_id == i->first);
4563                 if(client->serialization_version == SER_FMT_VER_INVALID)
4564                         continue;
4565                 // Get player
4566                 Player *player = m_env->getPlayer(client->peer_id);
4567                 // Get name of player
4568                 std::wstring name = L"unknown";
4569                 if(player != NULL)
4570                         name = narrow_to_wide(player->getName());
4571                 // Add name to information string
4572                 if(!first)
4573                         os<<L",";
4574                 else
4575                         first = false;
4576                 os<<name;
4577         }
4578         os<<L"}";
4579         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
4580                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
4581         if(g_settings->get("motd") != "")
4582                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
4583         return os.str();
4584 }
4585
4586 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
4587 {
4588         std::set<std::string> privs;
4589         scriptapi_get_auth(m_lua, name, NULL, &privs);
4590         return privs;
4591 }
4592
4593 bool Server::checkPriv(const std::string &name, const std::string &priv)
4594 {
4595         std::set<std::string> privs = getPlayerEffectivePrivs(name);
4596         return (privs.count(priv) != 0);
4597 }
4598
4599 void Server::reportPrivsModified(const std::string &name)
4600 {
4601         if(name == ""){
4602                 for(std::map<u16, RemoteClient*>::iterator
4603                                 i = m_clients.begin();
4604                                 i != m_clients.end(); ++i){
4605                         RemoteClient *client = i->second;
4606                         Player *player = m_env->getPlayer(client->peer_id);
4607                         reportPrivsModified(player->getName());
4608                 }
4609         } else {
4610                 Player *player = m_env->getPlayer(name.c_str());
4611                 if(!player)
4612                         return;
4613                 SendPlayerPrivileges(player->peer_id);
4614                 PlayerSAO *sao = player->getPlayerSAO();
4615                 if(!sao)
4616                         return;
4617                 sao->updatePrivileges(
4618                                 getPlayerEffectivePrivs(name),
4619                                 isSingleplayer());
4620         }
4621 }
4622
4623 void Server::reportInventoryFormspecModified(const std::string &name)
4624 {
4625         Player *player = m_env->getPlayer(name.c_str());
4626         if(!player)
4627                 return;
4628         SendPlayerInventoryFormspec(player->peer_id);
4629 }
4630
4631 // Saves g_settings to configpath given at initialization
4632 void Server::saveConfig()
4633 {
4634         if(m_path_config != "")
4635                 g_settings->updateConfigFile(m_path_config.c_str());
4636 }
4637
4638 void Server::notifyPlayer(const char *name, const std::wstring msg)
4639 {
4640         Player *player = m_env->getPlayer(name);
4641         if(!player)
4642                 return;
4643         SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
4644 }
4645
4646 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
4647 {
4648         Player *player = m_env->getPlayer(playername);
4649
4650         if(!player)
4651         {
4652                 infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
4653                 return false;
4654         }
4655
4656         SendShowFormspecMessage(player->peer_id, formspec, formname);
4657         return true;
4658 }
4659
4660 bool Server::hudadd(const char *playername, const u32 &id, HudElement* form)
4661 {
4662         Player *player = m_env->getPlayer(playername);
4663
4664         if(!player)
4665         {
4666                 infostream<<"hudadd: couldn't find player:"<<playername<<std::endl;
4667                 return false;
4668         }
4669
4670         SendHUDAdd(player->peer_id, id, form);
4671         return true;
4672 }
4673
4674 bool Server::hudrm(const char *playername, const u32 &id)
4675 {
4676         Player *player = m_env->getPlayer(playername);
4677
4678         if(!player)
4679         {
4680                 infostream<<"hudrm: couldn't find player:"<<playername<<std::endl;
4681                 return false;
4682         }
4683
4684         SendHUDRm(player->peer_id, id);
4685         return true;
4686 }
4687
4688 bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, v2f data)
4689 {
4690         Player *player = m_env->getPlayer(playername);
4691
4692         if(!player)
4693         {
4694                 infostream<<"hudchange: couldn't find player:"<<playername<<std::endl;
4695                 return false;
4696         }
4697
4698         SendHUDChange(player->peer_id, id, stat, data);
4699         return true;
4700 }
4701
4702 bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, std::string data)
4703 {
4704         Player *player = m_env->getPlayer(playername);
4705
4706         if(!player)
4707         {
4708                 infostream<<"hudchange: couldn't find player:"<<playername<<std::endl;
4709                 return false;
4710         }
4711
4712         SendHUDChange(player->peer_id, id, stat, data);
4713         return true;
4714 }
4715
4716 bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, u32 data)
4717 {
4718         Player *player = m_env->getPlayer(playername);
4719
4720         if(!player)
4721         {
4722                 infostream<<"hudchange: couldn't find player:"<<playername<<std::endl;
4723                 return false;
4724         }
4725
4726         SendHUDChange(player->peer_id, id, stat, data);
4727         return true;
4728 }
4729
4730 void Server::notifyPlayers(const std::wstring msg)
4731 {
4732         BroadcastChatMessage(msg);
4733 }
4734
4735 void Server::spawnParticle(const char *playername, v3f pos,
4736                 v3f velocity, v3f acceleration,
4737                 float expirationtime, float size, bool
4738                 collisiondetection, std::string texture)
4739 {
4740         Player *player = m_env->getPlayer(playername);
4741         if(!player)
4742                 return;
4743         SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
4744                         expirationtime, size, collisiondetection, texture);
4745 }
4746
4747 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
4748                 float expirationtime, float size,
4749                 bool collisiondetection, std::string texture)
4750 {
4751         SendSpawnParticleAll(pos, velocity, acceleration,
4752                         expirationtime, size, collisiondetection, texture);
4753 }
4754
4755 u32 Server::addParticleSpawner(const char *playername,
4756                 u16 amount, float spawntime,
4757                 v3f minpos, v3f maxpos,
4758                 v3f minvel, v3f maxvel,
4759                 v3f minacc, v3f maxacc,
4760                 float minexptime, float maxexptime,
4761                 float minsize, float maxsize,
4762                 bool collisiondetection, std::string texture)
4763 {
4764         Player *player = m_env->getPlayer(playername);
4765         if(!player)
4766                 return -1;
4767
4768         u32 id = 0;
4769         for(;;) // look for unused particlespawner id
4770         {
4771                 id++;
4772                 if (std::find(m_particlespawner_ids.begin(),
4773                                 m_particlespawner_ids.end(), id)
4774                                 == m_particlespawner_ids.end())
4775                 {
4776                         m_particlespawner_ids.push_back(id);
4777                         break;
4778                 }
4779         }
4780
4781         SendAddParticleSpawner(player->peer_id, amount, spawntime,
4782                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
4783                 minexptime, maxexptime, minsize, maxsize,
4784                 collisiondetection, texture, id);
4785
4786         return id;
4787 }
4788
4789 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
4790                 v3f minpos, v3f maxpos,
4791                 v3f minvel, v3f maxvel,
4792                 v3f minacc, v3f maxacc,
4793                 float minexptime, float maxexptime,
4794                 float minsize, float maxsize,
4795                 bool collisiondetection, std::string texture)
4796 {
4797         u32 id = 0;
4798         for(;;) // look for unused particlespawner id
4799         {
4800                 id++;
4801                 if (std::find(m_particlespawner_ids.begin(),
4802                                 m_particlespawner_ids.end(), id)
4803                                 == m_particlespawner_ids.end())
4804                 {
4805                         m_particlespawner_ids.push_back(id);
4806                         break;
4807                 }
4808         }
4809
4810         SendAddParticleSpawnerAll(amount, spawntime,
4811                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
4812                 minexptime, maxexptime, minsize, maxsize,
4813                 collisiondetection, texture, id);
4814
4815         return id;
4816 }
4817
4818 void Server::deleteParticleSpawner(const char *playername, u32 id)
4819 {
4820         Player *player = m_env->getPlayer(playername);
4821         if(!player)
4822                 return;
4823
4824         m_particlespawner_ids.erase(
4825                         std::remove(m_particlespawner_ids.begin(),
4826                         m_particlespawner_ids.end(), id),
4827                         m_particlespawner_ids.end());
4828         SendDeleteParticleSpawner(player->peer_id, id);
4829 }
4830
4831 void Server::deleteParticleSpawnerAll(u32 id)
4832 {
4833         m_particlespawner_ids.erase(
4834                         std::remove(m_particlespawner_ids.begin(),
4835                         m_particlespawner_ids.end(), id),
4836                         m_particlespawner_ids.end());
4837         SendDeleteParticleSpawnerAll(id);
4838 }
4839
4840 void Server::queueBlockEmerge(v3s16 blockpos, bool allow_generate)
4841 {
4842         m_emerge->enqueueBlockEmerge(PEER_ID_INEXISTENT, blockpos, allow_generate);
4843 }
4844
4845 Inventory* Server::createDetachedInventory(const std::string &name)
4846 {
4847         if(m_detached_inventories.count(name) > 0){
4848                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
4849                 delete m_detached_inventories[name];
4850         } else {
4851                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
4852         }
4853         Inventory *inv = new Inventory(m_itemdef);
4854         assert(inv);
4855         m_detached_inventories[name] = inv;
4856         sendDetachedInventoryToAll(name);
4857         return inv;
4858 }
4859
4860 class BoolScopeSet
4861 {
4862 public:
4863         BoolScopeSet(bool *dst, bool val):
4864                 m_dst(dst)
4865         {
4866                 m_orig_state = *m_dst;
4867                 *m_dst = val;
4868         }
4869         ~BoolScopeSet()
4870         {
4871                 *m_dst = m_orig_state;
4872         }
4873 private:
4874         bool *m_dst;
4875         bool m_orig_state;
4876 };
4877
4878 // actions: time-reversed list
4879 // Return value: success/failure
4880 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
4881                 std::list<std::string> *log)
4882 {
4883         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
4884         ServerMap *map = (ServerMap*)(&m_env->getMap());
4885         // Disable rollback report sink while reverting
4886         BoolScopeSet rollback_scope_disable(&m_rollback_sink_enabled, false);
4887
4888         // Fail if no actions to handle
4889         if(actions.empty()){
4890                 log->push_back("Nothing to do.");
4891                 return false;
4892         }
4893
4894         int num_tried = 0;
4895         int num_failed = 0;
4896
4897         for(std::list<RollbackAction>::const_iterator
4898                         i = actions.begin();
4899                         i != actions.end(); i++)
4900         {
4901                 const RollbackAction &action = *i;
4902                 num_tried++;
4903                 bool success = action.applyRevert(map, this, this);
4904                 if(!success){
4905                         num_failed++;
4906                         std::ostringstream os;
4907                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
4908                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
4909                         if(log)
4910                                 log->push_back(os.str());
4911                 }else{
4912                         std::ostringstream os;
4913                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
4914                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
4915                         if(log)
4916                                 log->push_back(os.str());
4917                 }
4918         }
4919
4920         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
4921                         <<" failed"<<std::endl;
4922
4923         // Call it done if less than half failed
4924         return num_failed <= num_tried/2;
4925 }
4926
4927 // IGameDef interface
4928 // Under envlock
4929 IItemDefManager* Server::getItemDefManager()
4930 {
4931         return m_itemdef;
4932 }
4933 INodeDefManager* Server::getNodeDefManager()
4934 {
4935         return m_nodedef;
4936 }
4937 ICraftDefManager* Server::getCraftDefManager()
4938 {
4939         return m_craftdef;
4940 }
4941 ITextureSource* Server::getTextureSource()
4942 {
4943         return NULL;
4944 }
4945 IShaderSource* Server::getShaderSource()
4946 {
4947         return NULL;
4948 }
4949 u16 Server::allocateUnknownNodeId(const std::string &name)
4950 {
4951         return m_nodedef->allocateDummy(name);
4952 }
4953 ISoundManager* Server::getSoundManager()
4954 {
4955         return &dummySoundManager;
4956 }
4957 MtEventManager* Server::getEventManager()
4958 {
4959         return m_event;
4960 }
4961 IRollbackReportSink* Server::getRollbackReportSink()
4962 {
4963         if(!m_enable_rollback_recording)
4964                 return NULL;
4965         if(!m_rollback_sink_enabled)
4966                 return NULL;
4967         return m_rollback;
4968 }
4969
4970 IWritableItemDefManager* Server::getWritableItemDefManager()
4971 {
4972         return m_itemdef;
4973 }
4974 IWritableNodeDefManager* Server::getWritableNodeDefManager()
4975 {
4976         return m_nodedef;
4977 }
4978 IWritableCraftDefManager* Server::getWritableCraftDefManager()
4979 {
4980         return m_craftdef;
4981 }
4982
4983 const ModSpec* Server::getModSpec(const std::string &modname)
4984 {
4985         for(std::vector<ModSpec>::iterator i = m_mods.begin();
4986                         i != m_mods.end(); i++){
4987                 const ModSpec &mod = *i;
4988                 if(mod.name == modname)
4989                         return &mod;
4990         }
4991         return NULL;
4992 }
4993 void Server::getModNames(std::list<std::string> &modlist)
4994 {
4995         for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++)
4996         {
4997                 modlist.push_back(i->name);
4998         }
4999 }
5000 std::string Server::getBuiltinLuaPath()
5001 {
5002         return porting::path_share + DIR_DELIM + "builtin";
5003 }
5004
5005 v3f findSpawnPos(ServerMap &map)
5006 {
5007         //return v3f(50,50,50)*BS;
5008
5009         v3s16 nodepos;
5010
5011 #if 0
5012         nodepos = v2s16(0,0);
5013         groundheight = 20;
5014 #endif
5015
5016 #if 1
5017         s16 water_level = map.m_mgparams->water_level;
5018
5019         // Try to find a good place a few times
5020         for(s32 i=0; i<1000; i++)
5021         {
5022                 s32 range = 1 + i;
5023                 // We're going to try to throw the player to this position
5024                 v2s16 nodepos2d = v2s16(-range + (myrand()%(range*2)),
5025                                 -range + (myrand()%(range*2)));
5026                 //v2s16 sectorpos = getNodeSectorPos(nodepos2d);
5027                 // Get ground height at point (fallbacks to heightmap function)
5028                 s16 groundheight = map.findGroundLevel(nodepos2d);
5029                 // Don't go underwater
5030                 if(groundheight <= water_level)
5031                 {
5032                         //infostream<<"-> Underwater"<<std::endl;
5033                         continue;
5034                 }
5035                 // Don't go to high places
5036                 if(groundheight > water_level + 6)
5037                 {
5038                         //infostream<<"-> Underwater"<<std::endl;
5039                         continue;
5040                 }
5041
5042                 nodepos = v3s16(nodepos2d.X, groundheight-2, nodepos2d.Y);
5043                 bool is_good = false;
5044                 s32 air_count = 0;
5045                 for(s32 i=0; i<10; i++){
5046                         v3s16 blockpos = getNodeBlockPos(nodepos);
5047                         map.emergeBlock(blockpos, true);
5048                         MapNode n = map.getNodeNoEx(nodepos);
5049                         if(n.getContent() == CONTENT_AIR){
5050                                 air_count++;
5051                                 if(air_count >= 2){
5052                                         is_good = true;
5053                                         nodepos.Y -= 1;
5054                                         break;
5055                                 }
5056                         }
5057                         nodepos.Y++;
5058                 }
5059                 if(is_good){
5060                         // Found a good place
5061                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
5062                         break;
5063                 }
5064         }
5065 #endif
5066
5067         return intToFloat(nodepos, BS);
5068 }
5069
5070 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
5071 {
5072         RemotePlayer *player = NULL;
5073         bool newplayer = false;
5074
5075         /*
5076                 Try to get an existing player
5077         */
5078         player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
5079
5080         // If player is already connected, cancel
5081         if(player != NULL && player->peer_id != 0)
5082         {
5083                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
5084                 return NULL;
5085         }
5086
5087         /*
5088                 If player with the wanted peer_id already exists, cancel.
5089         */
5090         if(m_env->getPlayer(peer_id) != NULL)
5091         {
5092                 infostream<<"emergePlayer(): Player with wrong name but same"
5093                                 " peer_id already exists"<<std::endl;
5094                 return NULL;
5095         }
5096
5097         /*
5098                 Create a new player if it doesn't exist yet
5099         */
5100         if(player == NULL)
5101         {
5102                 newplayer = true;
5103                 player = new RemotePlayer(this);
5104                 player->updateName(name);
5105
5106                 /* Set player position */
5107                 infostream<<"Server: Finding spawn place for player \""
5108                                 <<name<<"\""<<std::endl;
5109                 v3f pos = findSpawnPos(m_env->getServerMap());
5110                 player->setPosition(pos);
5111
5112                 /* Add player to environment */
5113                 m_env->addPlayer(player);
5114         }
5115
5116         /*
5117                 Create a new player active object
5118         */
5119         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
5120                         getPlayerEffectivePrivs(player->getName()),
5121                         isSingleplayer());
5122
5123         /* Add object to environment */
5124         m_env->addActiveObject(playersao);
5125
5126         /* Run scripts */
5127         if(newplayer)
5128                 scriptapi_on_newplayer(m_lua, playersao);
5129
5130         scriptapi_on_joinplayer(m_lua, playersao);
5131
5132         return playersao;
5133 }
5134
5135 void Server::handlePeerChange(PeerChange &c)
5136 {
5137         JMutexAutoLock envlock(m_env_mutex);
5138         JMutexAutoLock conlock(m_con_mutex);
5139
5140         if(c.type == PEER_ADDED)
5141         {
5142                 /*
5143                         Add
5144                 */
5145
5146                 // Error check
5147                 std::map<u16, RemoteClient*>::iterator n;
5148                 n = m_clients.find(c.peer_id);
5149                 // The client shouldn't already exist
5150                 assert(n == m_clients.end());
5151
5152                 // Create client
5153                 RemoteClient *client = new RemoteClient();
5154                 client->peer_id = c.peer_id;
5155                 m_clients[client->peer_id] = client;
5156
5157         } // PEER_ADDED
5158         else if(c.type == PEER_REMOVED)
5159         {
5160                 /*
5161                         Delete
5162                 */
5163
5164                 // Error check
5165                 std::map<u16, RemoteClient*>::iterator n;
5166                 n = m_clients.find(c.peer_id);
5167                 // The client should exist
5168                 assert(n != m_clients.end());
5169
5170                 /*
5171                         Mark objects to be not known by the client
5172                 */
5173                 RemoteClient *client = n->second;
5174                 // Handle objects
5175                 for(std::set<u16>::iterator
5176                                 i = client->m_known_objects.begin();
5177                                 i != client->m_known_objects.end(); ++i)
5178                 {
5179                         // Get object
5180                         u16 id = *i;
5181                         ServerActiveObject* obj = m_env->getActiveObject(id);
5182
5183                         if(obj && obj->m_known_by_count > 0)
5184                                 obj->m_known_by_count--;
5185                 }
5186
5187                 /*
5188                         Clear references to playing sounds
5189                 */
5190                 for(std::map<s32, ServerPlayingSound>::iterator
5191                                 i = m_playing_sounds.begin();
5192                                 i != m_playing_sounds.end();)
5193                 {
5194                         ServerPlayingSound &psound = i->second;
5195                         psound.clients.erase(c.peer_id);
5196                         if(psound.clients.size() == 0)
5197                                 m_playing_sounds.erase(i++);
5198                         else
5199                                 i++;
5200                 }
5201
5202                 Player *player = m_env->getPlayer(c.peer_id);
5203
5204                 // Collect information about leaving in chat
5205                 std::wstring message;
5206                 {
5207                         if(player != NULL)
5208                         {
5209                                 std::wstring name = narrow_to_wide(player->getName());
5210                                 message += L"*** ";
5211                                 message += name;
5212                                 message += L" left the game.";
5213                                 if(c.timeout)
5214                                         message += L" (timed out)";
5215                         }
5216                 }
5217
5218                 /* Run scripts and remove from environment */
5219                 {
5220                         if(player != NULL)
5221                         {
5222                                 PlayerSAO *playersao = player->getPlayerSAO();
5223                                 assert(playersao);
5224
5225                                 scriptapi_on_leaveplayer(m_lua, playersao);
5226
5227                                 playersao->disconnected();
5228                         }
5229                 }
5230
5231                 /*
5232                         Print out action
5233                 */
5234                 {
5235                         if(player != NULL)
5236                         {
5237                                 std::ostringstream os(std::ios_base::binary);
5238                                 for(std::map<u16, RemoteClient*>::iterator
5239                                         i = m_clients.begin();
5240                                         i != m_clients.end(); ++i)
5241                                 {
5242                                         RemoteClient *client = i->second;
5243                                         assert(client->peer_id == i->first);
5244                                         if(client->serialization_version == SER_FMT_VER_INVALID)
5245                                                 continue;
5246                                         // Get player
5247                                         Player *player = m_env->getPlayer(client->peer_id);
5248                                         if(!player)
5249                                                 continue;
5250                                         // Get name of player
5251                                         os<<player->getName()<<" ";
5252                                 }
5253
5254                                 actionstream<<player->getName()<<" "
5255                                                 <<(c.timeout?"times out.":"leaves game.")
5256                                                 <<" List of players: "
5257                                                 <<os.str()<<std::endl;
5258                         }
5259                 }
5260
5261                 // Delete client
5262                 delete m_clients[c.peer_id];
5263                 m_clients.erase(c.peer_id);
5264
5265                 // Send player info to all remaining clients
5266                 //SendPlayerInfos();
5267
5268                 // Send leave chat message to all remaining clients
5269                 if(message.length() != 0)
5270                         BroadcastChatMessage(message);
5271
5272         } // PEER_REMOVED
5273         else
5274         {
5275                 assert(0);
5276         }
5277 }
5278
5279 void Server::handlePeerChanges()
5280 {
5281         while(m_peer_change_queue.size() > 0)
5282         {
5283                 PeerChange c = m_peer_change_queue.pop_front();
5284
5285                 verbosestream<<"Server: Handling peer change: "
5286                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
5287                                 <<std::endl;
5288
5289                 handlePeerChange(c);
5290         }
5291 }
5292
5293 void dedicated_server_loop(Server &server, bool &kill)
5294 {
5295         DSTACK(__FUNCTION_NAME);
5296
5297         verbosestream<<"dedicated_server_loop()"<<std::endl;
5298
5299         IntervalLimiter m_profiler_interval;
5300
5301         for(;;)
5302         {
5303                 float steplen = g_settings->getFloat("dedicated_server_step");
5304                 // This is kind of a hack but can be done like this
5305                 // because server.step() is very light
5306                 {
5307                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
5308                         sleep_ms((int)(steplen*1000.0));
5309                 }
5310                 server.step(steplen);
5311
5312                 if(server.getShutdownRequested() || kill)
5313                 {
5314                         infostream<<"Dedicated server quitting"<<std::endl;
5315 #if USE_CURL
5316                         if(g_settings->getBool("server_announce") == true)
5317                                 ServerList::sendAnnounce("delete");
5318 #endif
5319                         break;
5320                 }
5321
5322                 /*
5323                         Profiler
5324                 */
5325                 float profiler_print_interval =
5326                                 g_settings->getFloat("profiler_print_interval");
5327                 if(profiler_print_interval != 0)
5328                 {
5329                         if(m_profiler_interval.step(steplen, profiler_print_interval))
5330                         {
5331                                 infostream<<"Profiler:"<<std::endl;
5332                                 g_profiler->print(infostream);
5333                                 g_profiler->clear();
5334                         }
5335                 }
5336         }
5337 }
5338
5339