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