]> git.lizzy.rs Git - dragonfireclient.git/blob - src/clientiface.cpp
Replace pause and message menu by formspec ones
[dragonfireclient.git] / src / clientiface.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2014 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 "clientiface.h"
21 #include "player.h"
22 #include "settings.h"
23 #include "mapblock.h"
24 #include "connection.h"
25 #include "environment.h"
26 #include "map.h"
27 #include "emerge.h"
28 #include "serverobject.h"              // TODO this is used for cleanup of only
29
30 #include "util/numeric.h"
31 #include "util/mathconstants.h"
32
33 #include "main.h"                      // for g_settings
34
35 void RemoteClient::GetNextBlocks(
36                 ServerEnvironment *env,
37                 EmergeManager * emerge,
38                 float dtime,
39                 std::vector<PrioritySortedBlockTransfer> &dest)
40 {
41         DSTACK(__FUNCTION_NAME);
42
43
44         // Increment timers
45         m_nothing_to_send_pause_timer -= dtime;
46         m_nearest_unsent_reset_timer += dtime;
47
48         if(m_nothing_to_send_pause_timer >= 0)
49                 return;
50
51         Player *player = env->getPlayer(peer_id);
52         // This can happen sometimes; clients and players are not in perfect sync.
53         if(player == NULL)
54                 return;
55
56         // Won't send anything if already sending
57         if(m_blocks_sending.size() >= g_settings->getU16
58                         ("max_simultaneous_block_sends_per_client"))
59         {
60                 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
61                 return;
62         }
63
64         v3f playerpos = player->getPosition();
65         v3f playerspeed = player->getSpeed();
66         v3f playerspeeddir(0,0,0);
67         if(playerspeed.getLength() > 1.0*BS)
68                 playerspeeddir = playerspeed / playerspeed.getLength();
69         // Predict to next block
70         v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
71
72         v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
73
74         v3s16 center = getNodeBlockPos(center_nodepos);
75
76         // Camera position and direction
77         v3f camera_pos = player->getEyePosition();
78         v3f camera_dir = v3f(0,0,1);
79         camera_dir.rotateYZBy(player->getPitch());
80         camera_dir.rotateXZBy(player->getYaw());
81
82         /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
83                         <<camera_dir.Z<<")"<<std::endl;*/
84
85         /*
86                 Get the starting value of the block finder radius.
87         */
88
89         if(m_last_center != center)
90         {
91                 m_nearest_unsent_d = 0;
92                 m_last_center = center;
93         }
94
95         /*infostream<<"m_nearest_unsent_reset_timer="
96                         <<m_nearest_unsent_reset_timer<<std::endl;*/
97
98         // Reset periodically to workaround for some bugs or stuff
99         if(m_nearest_unsent_reset_timer > 20.0)
100         {
101                 m_nearest_unsent_reset_timer = 0;
102                 m_nearest_unsent_d = 0;
103                 //infostream<<"Resetting m_nearest_unsent_d for "
104                 //              <<server->getPlayerName(peer_id)<<std::endl;
105         }
106
107         //s16 last_nearest_unsent_d = m_nearest_unsent_d;
108         s16 d_start = m_nearest_unsent_d;
109
110         //infostream<<"d_start="<<d_start<<std::endl;
111
112         u16 max_simul_sends_setting = g_settings->getU16
113                         ("max_simultaneous_block_sends_per_client");
114         u16 max_simul_sends_usually = max_simul_sends_setting;
115
116         /*
117                 Check the time from last addNode/removeNode.
118
119                 Decrease send rate if player is building stuff.
120         */
121         m_time_from_building += dtime;
122         if(m_time_from_building < g_settings->getFloat(
123                                 "full_block_send_enable_min_time_from_building"))
124         {
125                 max_simul_sends_usually
126                         = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
127         }
128
129         /*
130                 Number of blocks sending + number of blocks selected for sending
131         */
132         u32 num_blocks_selected = m_blocks_sending.size();
133
134         /*
135                 next time d will be continued from the d from which the nearest
136                 unsent block was found this time.
137
138                 This is because not necessarily any of the blocks found this
139                 time are actually sent.
140         */
141         s32 new_nearest_unsent_d = -1;
142
143         s16 d_max = g_settings->getS16("max_block_send_distance");
144         s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
145
146         // Don't loop very much at a time
147         s16 max_d_increment_at_time = 2;
148         if(d_max > d_start + max_d_increment_at_time)
149                 d_max = d_start + max_d_increment_at_time;
150
151         s32 nearest_emerged_d = -1;
152         s32 nearest_emergefull_d = -1;
153         s32 nearest_sent_d = -1;
154         bool queue_is_full = false;
155
156         s16 d;
157         for(d = d_start; d <= d_max; d++)
158         {
159                 /*
160                         Get the border/face dot coordinates of a "d-radiused"
161                         box
162                 */
163                 std::list<v3s16> list;
164                 getFacePositions(list, d);
165
166                 std::list<v3s16>::iterator li;
167                 for(li=list.begin(); li!=list.end(); ++li)
168                 {
169                         v3s16 p = *li + center;
170
171                         /*
172                                 Send throttling
173                                 - Don't allow too many simultaneous transfers
174                                 - EXCEPT when the blocks are very close
175
176                                 Also, don't send blocks that are already flying.
177                         */
178
179                         // Start with the usual maximum
180                         u16 max_simul_dynamic = max_simul_sends_usually;
181
182                         // If block is very close, allow full maximum
183                         if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
184                                 max_simul_dynamic = max_simul_sends_setting;
185
186                         // Don't select too many blocks for sending
187                         if(num_blocks_selected >= max_simul_dynamic)
188                         {
189                                 queue_is_full = true;
190                                 goto queue_full_break;
191                         }
192
193                         // Don't send blocks that are currently being transferred
194                         if(m_blocks_sending.find(p) != m_blocks_sending.end())
195                                 continue;
196
197                         /*
198                                 Do not go over-limit
199                         */
200                         if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
201                         || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
202                         || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
203                         || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
204                         || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
205                         || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
206                                 continue;
207
208                         // If this is true, inexistent block will be made from scratch
209                         bool generate = d <= d_max_gen;
210
211                         {
212                                 /*// Limit the generating area vertically to 2/3
213                                 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
214                                         generate = false;*/
215
216                                 // Limit the send area vertically to 1/2
217                                 if(abs(p.Y - center.Y) > d_max / 2)
218                                         continue;
219                         }
220
221                         /*
222                                 Don't generate or send if not in sight
223                                 FIXME This only works if the client uses a small enough
224                                 FOV setting. The default of 72 degrees is fine.
225                         */
226
227                         float camera_fov = (72.0*M_PI/180) * 4./3.;
228                         if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
229                         {
230                                 continue;
231                         }
232
233                         /*
234                                 Don't send already sent blocks
235                         */
236                         {
237                                 if(m_blocks_sent.find(p) != m_blocks_sent.end())
238                                 {
239                                         continue;
240                                 }
241                         }
242
243                         /*
244                                 Check if map has this block
245                         */
246                         MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
247
248                         bool surely_not_found_on_disk = false;
249                         bool block_is_invalid = false;
250                         if(block != NULL)
251                         {
252                                 // Reset usage timer, this block will be of use in the future.
253                                 block->resetUsageTimer();
254
255                                 // Block is dummy if data doesn't exist.
256                                 // It means it has been not found from disk and not generated
257                                 if(block->isDummy())
258                                 {
259                                         surely_not_found_on_disk = true;
260                                 }
261
262                                 // Block is valid if lighting is up-to-date and data exists
263                                 if(block->isValid() == false)
264                                 {
265                                         block_is_invalid = true;
266                                 }
267
268                                 if(block->isGenerated() == false)
269                                         block_is_invalid = true;
270
271                                 /*
272                                         If block is not close, don't send it unless it is near
273                                         ground level.
274
275                                         Block is near ground level if night-time mesh
276                                         differs from day-time mesh.
277                                 */
278                                 if(d >= 4)
279                                 {
280                                         if(block->getDayNightDiff() == false)
281                                                 continue;
282                                 }
283                         }
284
285                         /*
286                                 If block has been marked to not exist on disk (dummy)
287                                 and generating new ones is not wanted, skip block.
288                         */
289                         if(generate == false && surely_not_found_on_disk == true)
290                         {
291                                 // get next one.
292                                 continue;
293                         }
294
295                         /*
296                                 Add inexistent block to emerge queue.
297                         */
298                         if(block == NULL || surely_not_found_on_disk || block_is_invalid)
299                         {
300                                 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
301                                         if (nearest_emerged_d == -1)
302                                                 nearest_emerged_d = d;
303                                 } else {
304                                         if (nearest_emergefull_d == -1)
305                                                 nearest_emergefull_d = d;
306                                         goto queue_full_break;
307                                 }
308
309                                 // get next one.
310                                 continue;
311                         }
312
313                         if(nearest_sent_d == -1)
314                                 nearest_sent_d = d;
315
316                         /*
317                                 Add block to send queue
318                         */
319                         PrioritySortedBlockTransfer q((float)d, p, peer_id);
320
321                         dest.push_back(q);
322
323                         num_blocks_selected += 1;
324                 }
325         }
326 queue_full_break:
327
328         // If nothing was found for sending and nothing was queued for
329         // emerging, continue next time browsing from here
330         if(nearest_emerged_d != -1){
331                 new_nearest_unsent_d = nearest_emerged_d;
332         } else if(nearest_emergefull_d != -1){
333                 new_nearest_unsent_d = nearest_emergefull_d;
334         } else {
335                 if(d > g_settings->getS16("max_block_send_distance")){
336                         new_nearest_unsent_d = 0;
337                         m_nothing_to_send_pause_timer = 2.0;
338                 } else {
339                         if(nearest_sent_d != -1)
340                                 new_nearest_unsent_d = nearest_sent_d;
341                         else
342                                 new_nearest_unsent_d = d;
343                 }
344         }
345
346         if(new_nearest_unsent_d != -1)
347                 m_nearest_unsent_d = new_nearest_unsent_d;
348 }
349
350 void RemoteClient::GotBlock(v3s16 p)
351 {
352         if(m_blocks_sending.find(p) != m_blocks_sending.end())
353                 m_blocks_sending.erase(p);
354         else
355         {
356                 m_excess_gotblocks++;
357         }
358         m_blocks_sent.insert(p);
359 }
360
361 void RemoteClient::SentBlock(v3s16 p)
362 {
363         if(m_blocks_sending.find(p) == m_blocks_sending.end())
364                 m_blocks_sending[p] = 0.0;
365         else
366                 infostream<<"RemoteClient::SentBlock(): Sent block"
367                                 " already in m_blocks_sending"<<std::endl;
368 }
369
370 void RemoteClient::SetBlockNotSent(v3s16 p)
371 {
372         m_nearest_unsent_d = 0;
373
374         if(m_blocks_sending.find(p) != m_blocks_sending.end())
375                 m_blocks_sending.erase(p);
376         if(m_blocks_sent.find(p) != m_blocks_sent.end())
377                 m_blocks_sent.erase(p);
378 }
379
380 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
381 {
382         m_nearest_unsent_d = 0;
383
384         for(std::map<v3s16, MapBlock*>::iterator
385                         i = blocks.begin();
386                         i != blocks.end(); ++i)
387         {
388                 v3s16 p = i->first;
389
390                 if(m_blocks_sending.find(p) != m_blocks_sending.end())
391                         m_blocks_sending.erase(p);
392                 if(m_blocks_sent.find(p) != m_blocks_sent.end())
393                         m_blocks_sent.erase(p);
394         }
395 }
396
397 void RemoteClient::notifyEvent(ClientStateEvent event)
398 {
399         switch (m_state)
400         {
401         case Invalid:
402                 assert("State update for client in invalid state" != 0);
403                 break;
404
405         case Created:
406                 switch(event)
407                 {
408                 case Init:
409                         m_state = InitSent;
410                         break;
411
412                 case Disconnect:
413                         m_state = Disconnecting;
414                         break;
415
416                 case SetDenied:
417                         m_state = Denied;
418                         break;
419
420                 /* GotInit2 SetDefinitionsSent SetMediaSent */
421                 default:
422                         assert("Invalid client state transition!" == 0);
423                 }
424                 break;
425
426         case Denied:
427                 /* don't do anything if in denied state */
428                 break;
429
430         case InitSent:
431                 switch(event)
432                 {
433                 case GotInit2:
434                         confirmSerializationVersion();
435                         m_state = InitDone;
436                         break;
437
438                 case Disconnect:
439                         m_state = Disconnecting;
440                         break;
441
442                 case SetDenied:
443                         m_state = Denied;
444                         break;
445
446                 /* Init SetDefinitionsSent SetMediaSent */
447                 default:
448                         assert("Invalid client state transition!" == 0);
449                 }
450                 break;
451
452         case InitDone:
453                 switch(event)
454                 {
455                 case SetDefinitionsSent:
456                         m_state = DefinitionsSent;
457                         break;
458
459                 case Disconnect:
460                         m_state = Disconnecting;
461                         break;
462
463                 case SetDenied:
464                         m_state = Denied;
465                         break;
466
467                 /* Init GotInit2 SetMediaSent */
468                 default:
469                         assert("Invalid client state transition!" == 0);
470                 }
471                 break;
472
473         case DefinitionsSent:
474                 switch(event)
475                 {
476                 case SetMediaSent:
477                         m_state = Active;
478                         break;
479
480                 case Disconnect:
481                         m_state = Disconnecting;
482                         break;
483
484                 case SetDenied:
485                         m_state = Denied;
486                         break;
487
488                 /* Init GotInit2 SetDefinitionsSent */
489                 default:
490                         assert("Invalid client state transition!" == 0);
491                 }
492                 break;
493
494         case Active:
495                 switch(event)
496                 {
497                 case SetDenied:
498                         m_state = Denied;
499                         break;
500
501                 case Disconnect:
502                         m_state = Disconnecting;
503                         break;
504
505                 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
506                 default:
507                         assert("Invalid client state transition!" == 0);
508                         break;
509                 }
510                 break;
511
512         case Disconnecting:
513                 /* we are already disconnecting */
514                 break;
515         }
516 }
517
518 ClientInterface::ClientInterface(con::Connection* con)
519 :
520         m_con(con),
521         m_env(NULL),
522         m_print_info_timer(0.0)
523 {
524
525 }
526 ClientInterface::~ClientInterface()
527 {
528         /*
529                 Delete clients
530         */
531         {
532                 JMutexAutoLock clientslock(m_clients_mutex);
533
534                 for(std::map<u16, RemoteClient*>::iterator
535                         i = m_clients.begin();
536                         i != m_clients.end(); ++i)
537                 {
538
539                         // Delete client
540                         delete i->second;
541                 }
542         }
543 }
544
545 std::list<u16> ClientInterface::getClientIDs(ClientState min_state)
546 {
547         std::list<u16> reply;
548         JMutexAutoLock clientslock(m_clients_mutex);
549
550         for(std::map<u16, RemoteClient*>::iterator
551                 i = m_clients.begin();
552                 i != m_clients.end(); ++i)
553         {
554                 if (i->second->getState() >= min_state)
555                         reply.push_back(i->second->peer_id);
556         }
557
558         return reply;
559 }
560
561 std::vector<std::string> ClientInterface::getPlayerNames()
562 {
563         return m_clients_names;
564 }
565
566
567 void ClientInterface::step(float dtime)
568 {
569         m_print_info_timer += dtime;
570         if(m_print_info_timer >= 30.0)
571         {
572                 m_print_info_timer = 0.0;
573                 UpdatePlayerList();
574         }
575 }
576
577 void ClientInterface::UpdatePlayerList()
578 {
579         if (m_env != NULL)
580                 {
581                 std::list<u16> clients = getClientIDs();
582                 m_clients_names.clear();
583
584
585                 if(clients.size() != 0)
586                         infostream<<"Players:"<<std::endl;
587                 for(std::list<u16>::iterator
588                         i = clients.begin();
589                         i != clients.end(); ++i)
590                 {
591                         Player *player = m_env->getPlayer(*i);
592                         if(player==NULL)
593                                 continue;
594                         infostream<<"* "<<player->getName()<<"\t";
595
596                         {
597                                 JMutexAutoLock clientslock(m_clients_mutex);
598                                 RemoteClient* client = lockedGetClientNoEx(*i);
599                                 if(client != NULL)
600                                         client->PrintInfo(infostream);
601                         }
602                         m_clients_names.push_back(player->getName());
603                 }
604         }
605 }
606
607 void ClientInterface::send(u16 peer_id,u8 channelnum,
608                 SharedBuffer<u8> data, bool reliable)
609 {
610         m_con->Send(peer_id, channelnum, data, reliable);
611 }
612
613 void ClientInterface::sendToAll(u16 channelnum,
614                 SharedBuffer<u8> data, bool reliable)
615 {
616         JMutexAutoLock clientslock(m_clients_mutex);
617         for(std::map<u16, RemoteClient*>::iterator
618                 i = m_clients.begin();
619                 i != m_clients.end(); ++i)
620         {
621                 RemoteClient *client = i->second;
622
623                 if (client->net_proto_version != 0)
624                 {
625                         m_con->Send(client->peer_id, channelnum, data, reliable);
626                 }
627         }
628 }
629
630 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
631 {
632         JMutexAutoLock clientslock(m_clients_mutex);
633         std::map<u16, RemoteClient*>::iterator n;
634         n = m_clients.find(peer_id);
635         // The client may not exist; clients are immediately removed if their
636         // access is denied, and this event occurs later then.
637         if(n == m_clients.end())
638                 return NULL;
639
640         if (n->second->getState() >= state_min)
641                 return n->second;
642         else
643                 return NULL;
644 }
645
646 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
647 {
648         std::map<u16, RemoteClient*>::iterator n;
649         n = m_clients.find(peer_id);
650         // The client may not exist; clients are immediately removed if their
651         // access is denied, and this event occurs later then.
652         if(n == m_clients.end())
653                 return NULL;
654
655         if (n->second->getState() >= state_min)
656                 return n->second;
657         else
658                 return NULL;
659 }
660
661 ClientState ClientInterface::getClientState(u16 peer_id)
662 {
663         JMutexAutoLock clientslock(m_clients_mutex);
664         std::map<u16, RemoteClient*>::iterator n;
665         n = m_clients.find(peer_id);
666         // The client may not exist; clients are immediately removed if their
667         // access is denied, and this event occurs later then.
668         if(n == m_clients.end())
669                 return Invalid;
670
671         return n->second->getState();
672 }
673
674 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
675 {
676         JMutexAutoLock clientslock(m_clients_mutex);
677         std::map<u16, RemoteClient*>::iterator n;
678         n = m_clients.find(peer_id);
679         // The client may not exist; clients are immediately removed if their
680         // access is denied, and this event occurs later then.
681         if(n != m_clients.end())
682                 n->second->setName(name);
683 }
684
685 void ClientInterface::DeleteClient(u16 peer_id)
686 {
687         JMutexAutoLock conlock(m_clients_mutex);
688
689         // Error check
690         std::map<u16, RemoteClient*>::iterator n;
691         n = m_clients.find(peer_id);
692         // The client may not exist; clients are immediately removed if their
693         // access is denied, and this event occurs later then.
694         if(n == m_clients.end())
695                 return;
696
697         /*
698                 Mark objects to be not known by the client
699         */
700         //TODO this should be done by client destructor!!!
701         RemoteClient *client = n->second;
702         // Handle objects
703         for(std::set<u16>::iterator
704                         i = client->m_known_objects.begin();
705                         i != client->m_known_objects.end(); ++i)
706         {
707                 // Get object
708                 u16 id = *i;
709                 ServerActiveObject* obj = m_env->getActiveObject(id);
710
711                 if(obj && obj->m_known_by_count > 0)
712                         obj->m_known_by_count--;
713         }
714
715         // Delete client
716         delete m_clients[peer_id];
717         m_clients.erase(peer_id);
718 }
719
720 void ClientInterface::CreateClient(u16 peer_id)
721 {
722         JMutexAutoLock conlock(m_clients_mutex);
723
724         // Error check
725         std::map<u16, RemoteClient*>::iterator n;
726         n = m_clients.find(peer_id);
727         // The client shouldn't already exist
728         if(n != m_clients.end()) return;
729
730         // Create client
731         RemoteClient *client = new RemoteClient();
732         client->peer_id = peer_id;
733         m_clients[client->peer_id] = client;
734 }
735
736 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
737 {
738         {
739                 JMutexAutoLock clientlock(m_clients_mutex);
740
741                 // Error check
742                 std::map<u16, RemoteClient*>::iterator n;
743                 n = m_clients.find(peer_id);
744
745                 // No client to deliver event
746                 if (n == m_clients.end())
747                         return;
748                 n->second->notifyEvent(event);
749         }
750
751         if ((event == SetMediaSent) || (event == Disconnect) || (event == SetDenied))
752         {
753                 UpdatePlayerList();
754         }
755 }
756
757 u16 ClientInterface::getProtocolVersion(u16 peer_id)
758 {
759         JMutexAutoLock conlock(m_clients_mutex);
760
761         // Error check
762         std::map<u16, RemoteClient*>::iterator n;
763         n = m_clients.find(peer_id);
764
765         // No client to deliver event
766         if (n == m_clients.end())
767                 return 0;
768
769         return n->second->net_proto_version;
770 }