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