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