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