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