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