3 Copyright (C) 2010-2014 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
22 #include "clientiface.h"
23 #include "util/numeric.h"
24 #include "util/mathconstants.h"
25 #include "remoteplayer.h"
28 #include "network/connection.h"
29 #include "environment.h"
32 #include "content_sao.h" // TODO this is used for cleanup of only
36 const char *ClientInterface::statenames[] = {
51 std::string ClientInterface::state2Name(ClientState state)
53 return statenames[state];
56 void RemoteClient::ResendBlockIfOnWire(v3s16 p)
58 // if this block is on wire, mark it for sending again as soon as possible
59 if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
64 void RemoteClient::GetNextBlocks (
65 ServerEnvironment *env,
66 EmergeManager * emerge,
68 std::vector<PrioritySortedBlockTransfer> &dest)
70 DSTACK(FUNCTION_NAME);
74 m_nothing_to_send_pause_timer -= dtime;
75 m_nearest_unsent_reset_timer += dtime;
77 if(m_nothing_to_send_pause_timer >= 0)
80 RemotePlayer *player = env->getPlayer(peer_id);
81 // This can happen sometimes; clients and players are not in perfect sync.
85 PlayerSAO *sao = player->getPlayerSAO();
89 // Won't send anything if already sending
90 if(m_blocks_sending.size() >= g_settings->getU16
91 ("max_simultaneous_block_sends_per_client"))
93 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
97 v3f playerpos = sao->getBasePosition();
98 v3f playerspeed = player->getSpeed();
99 v3f playerspeeddir(0,0,0);
100 if(playerspeed.getLength() > 1.0*BS)
101 playerspeeddir = playerspeed / playerspeed.getLength();
102 // Predict to next block
103 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
105 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
107 v3s16 center = getNodeBlockPos(center_nodepos);
109 // Camera position and direction
110 v3f camera_pos = sao->getEyePosition();
111 v3f camera_dir = v3f(0,0,1);
112 camera_dir.rotateYZBy(sao->getPitch());
113 camera_dir.rotateXZBy(sao->getYaw());
115 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
116 <<camera_dir.Z<<")"<<std::endl;*/
119 Get the starting value of the block finder radius.
122 if(m_last_center != center)
124 m_nearest_unsent_d = 0;
125 m_last_center = center;
128 /*infostream<<"m_nearest_unsent_reset_timer="
129 <<m_nearest_unsent_reset_timer<<std::endl;*/
131 // Reset periodically to workaround for some bugs or stuff
132 if(m_nearest_unsent_reset_timer > 20.0)
134 m_nearest_unsent_reset_timer = 0;
135 m_nearest_unsent_d = 0;
136 //infostream<<"Resetting m_nearest_unsent_d for "
137 // <<server->getPlayerName(peer_id)<<std::endl;
140 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
141 s16 d_start = m_nearest_unsent_d;
143 //infostream<<"d_start="<<d_start<<std::endl;
145 u16 max_simul_sends_setting = g_settings->getU16
146 ("max_simultaneous_block_sends_per_client");
147 u16 max_simul_sends_usually = max_simul_sends_setting;
150 Check the time from last addNode/removeNode.
152 Decrease send rate if player is building stuff.
154 m_time_from_building += dtime;
155 if(m_time_from_building < g_settings->getFloat(
156 "full_block_send_enable_min_time_from_building"))
158 max_simul_sends_usually
159 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
163 Number of blocks sending + number of blocks selected for sending
165 u32 num_blocks_selected = m_blocks_sending.size();
168 next time d will be continued from the d from which the nearest
169 unsent block was found this time.
171 This is because not necessarily any of the blocks found this
172 time are actually sent.
174 s32 new_nearest_unsent_d = -1;
176 const s16 full_d_max = g_settings->getS16("max_block_send_distance");
177 const s16 d_opt = g_settings->getS16("block_send_optimize_distance");
178 const s16 d_blocks_in_sight = full_d_max * BS * MAP_BLOCKSIZE;
180 s16 d_max = full_d_max;
181 s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
183 // Don't loop very much at a time
184 s16 max_d_increment_at_time = 2;
185 if(d_max > d_start + max_d_increment_at_time)
186 d_max = d_start + max_d_increment_at_time;
188 s32 nearest_emerged_d = -1;
189 s32 nearest_emergefull_d = -1;
190 s32 nearest_sent_d = -1;
191 //bool queue_is_full = false;
194 for(d = d_start; d <= d_max; d++) {
196 Get the border/face dot coordinates of a "d-radiused"
199 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
201 std::vector<v3s16>::iterator li;
202 for(li = list.begin(); li != list.end(); ++li) {
203 v3s16 p = *li + center;
207 - Don't allow too many simultaneous transfers
208 - EXCEPT when the blocks are very close
210 Also, don't send blocks that are already flying.
213 // Start with the usual maximum
214 u16 max_simul_dynamic = max_simul_sends_usually;
216 // If block is very close, allow full maximum
217 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
218 max_simul_dynamic = max_simul_sends_setting;
220 // Don't select too many blocks for sending
221 if (num_blocks_selected >= max_simul_dynamic) {
222 //queue_is_full = true;
223 goto queue_full_break;
226 // Don't send blocks that are currently being transferred
227 if (m_blocks_sending.find(p) != m_blocks_sending.end())
233 if (blockpos_over_limit(p))
236 // If this is true, inexistent block will be made from scratch
237 bool generate = d <= d_max_gen;
240 Don't generate or send if not in sight
241 FIXME This only works if the client uses a small enough
242 FOV setting. The default of 72 degrees is fine.
245 float camera_fov = (72.0*M_PI/180) * 4./3.;
246 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, d_blocks_in_sight) == false)
252 Don't send already sent blocks
255 if(m_blocks_sent.find(p) != m_blocks_sent.end())
262 Check if map has this block
264 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
266 bool surely_not_found_on_disk = false;
267 bool block_is_invalid = false;
270 // Reset usage timer, this block will be of use in the future.
271 block->resetUsageTimer();
273 // Block is dummy if data doesn't exist.
274 // It means it has been not found from disk and not generated
277 surely_not_found_on_disk = true;
280 // Block is valid if lighting is up-to-date and data exists
281 if(block->isValid() == false)
283 block_is_invalid = true;
286 if(block->isGenerated() == false)
287 block_is_invalid = true;
290 If block is not close, don't send it unless it is near
293 Block is near ground level if night-time mesh
294 differs from day-time mesh.
298 if(block->getDayNightDiff() == false)
304 If block has been marked to not exist on disk (dummy)
305 and generating new ones is not wanted, skip block.
307 if(generate == false && surely_not_found_on_disk == true)
314 Add inexistent block to emerge queue.
316 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
318 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
319 if (nearest_emerged_d == -1)
320 nearest_emerged_d = d;
322 if (nearest_emergefull_d == -1)
323 nearest_emergefull_d = d;
324 goto queue_full_break;
331 if(nearest_sent_d == -1)
335 Add block to send queue
337 PrioritySortedBlockTransfer q((float)d, p, peer_id);
341 num_blocks_selected += 1;
346 // If nothing was found for sending and nothing was queued for
347 // emerging, continue next time browsing from here
348 if(nearest_emerged_d != -1){
349 new_nearest_unsent_d = nearest_emerged_d;
350 } else if(nearest_emergefull_d != -1){
351 new_nearest_unsent_d = nearest_emergefull_d;
353 if(d > g_settings->getS16("max_block_send_distance")){
354 new_nearest_unsent_d = 0;
355 m_nothing_to_send_pause_timer = 2.0;
357 if(nearest_sent_d != -1)
358 new_nearest_unsent_d = nearest_sent_d;
360 new_nearest_unsent_d = d;
364 if(new_nearest_unsent_d != -1)
365 m_nearest_unsent_d = new_nearest_unsent_d;
368 void RemoteClient::GotBlock(v3s16 p)
370 if (m_blocks_modified.find(p) == m_blocks_modified.end()) {
371 if (m_blocks_sending.find(p) != m_blocks_sending.end())
372 m_blocks_sending.erase(p);
374 m_excess_gotblocks++;
376 m_blocks_sent.insert(p);
380 void RemoteClient::SentBlock(v3s16 p)
382 if (m_blocks_modified.find(p) != m_blocks_modified.end())
383 m_blocks_modified.erase(p);
385 if(m_blocks_sending.find(p) == m_blocks_sending.end())
386 m_blocks_sending[p] = 0.0;
388 infostream<<"RemoteClient::SentBlock(): Sent block"
389 " already in m_blocks_sending"<<std::endl;
392 void RemoteClient::SetBlockNotSent(v3s16 p)
394 m_nearest_unsent_d = 0;
395 m_nothing_to_send_pause_timer = 0;
397 if(m_blocks_sending.find(p) != m_blocks_sending.end())
398 m_blocks_sending.erase(p);
399 if(m_blocks_sent.find(p) != m_blocks_sent.end())
400 m_blocks_sent.erase(p);
401 m_blocks_modified.insert(p);
404 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
406 m_nearest_unsent_d = 0;
407 m_nothing_to_send_pause_timer = 0;
409 for(std::map<v3s16, MapBlock*>::iterator
411 i != blocks.end(); ++i)
414 m_blocks_modified.insert(p);
416 if(m_blocks_sending.find(p) != m_blocks_sending.end())
417 m_blocks_sending.erase(p);
418 if(m_blocks_sent.find(p) != m_blocks_sent.end())
419 m_blocks_sent.erase(p);
423 void RemoteClient::notifyEvent(ClientStateEvent event)
425 std::ostringstream myerror;
429 //intentionally do nothing
434 m_state = CS_HelloSent;
437 m_state = CS_AwaitingInit2;
440 m_state = CS_Disconnecting;
445 /* GotInit2 SetDefinitionsSent SetMediaSent */
447 myerror << "Created: Invalid client state transition! " << event;
448 throw ClientStateError(myerror.str());
452 /* don't do anything if in denied state */
458 m_state = CS_AwaitingInit2;
459 if ((chosen_mech == AUTH_MECHANISM_SRP)
460 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
461 srp_verifier_delete((SRPVerifier *) auth_data);
462 chosen_mech = AUTH_MECHANISM_NONE;
465 m_state = CS_Disconnecting;
469 if ((chosen_mech == AUTH_MECHANISM_SRP)
470 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
471 srp_verifier_delete((SRPVerifier *) auth_data);
472 chosen_mech = AUTH_MECHANISM_NONE;
475 myerror << "HelloSent: Invalid client state transition! " << event;
476 throw ClientStateError(myerror.str());
479 case CS_AwaitingInit2:
483 confirmSerializationVersion();
484 m_state = CS_InitDone;
487 m_state = CS_Disconnecting;
493 /* Init SetDefinitionsSent SetMediaSent */
495 myerror << "InitSent: Invalid client state transition! " << event;
496 throw ClientStateError(myerror.str());
503 case CSE_SetDefinitionsSent:
504 m_state = CS_DefinitionsSent;
507 m_state = CS_Disconnecting;
513 /* Init GotInit2 SetMediaSent */
515 myerror << "InitDone: Invalid client state transition! " << event;
516 throw ClientStateError(myerror.str());
519 case CS_DefinitionsSent:
522 case CSE_SetClientReady:
526 m_state = CS_Disconnecting;
531 /* Init GotInit2 SetDefinitionsSent */
533 myerror << "DefinitionsSent: Invalid client state transition! " << event;
534 throw ClientStateError(myerror.str());
544 m_state = CS_Disconnecting;
546 case CSE_SudoSuccess:
547 m_state = CS_SudoMode;
548 if ((chosen_mech == AUTH_MECHANISM_SRP)
549 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
550 srp_verifier_delete((SRPVerifier *) auth_data);
551 chosen_mech = AUTH_MECHANISM_NONE;
553 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
555 myerror << "Active: Invalid client state transition! " << event;
556 throw ClientStateError(myerror.str());
567 m_state = CS_Disconnecting;
573 myerror << "Active: Invalid client state transition! " << event;
574 throw ClientStateError(myerror.str());
578 case CS_Disconnecting:
579 /* we are already disconnecting */
584 u32 RemoteClient::uptime()
586 return getTime(PRECISION_SECONDS) - m_connection_time;
589 ClientInterface::ClientInterface(con::Connection* con)
593 m_print_info_timer(0.0)
597 ClientInterface::~ClientInterface()
603 MutexAutoLock clientslock(m_clients_mutex);
605 for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
606 i != m_clients.end(); ++i) {
613 std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
615 std::vector<u16> reply;
616 MutexAutoLock clientslock(m_clients_mutex);
618 for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
619 i != m_clients.end(); ++i) {
620 if (i->second->getState() >= min_state)
621 reply.push_back(i->second->peer_id);
627 void ClientInterface::step(float dtime)
629 m_print_info_timer += dtime;
630 if(m_print_info_timer >= 30.0)
632 m_print_info_timer = 0.0;
637 void ClientInterface::UpdatePlayerList()
640 std::vector<u16> clients = getClientIDs();
641 m_clients_names.clear();
645 infostream<<"Players:"<<std::endl;
647 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
648 RemotePlayer *player = m_env->getPlayer(*i);
653 infostream << "* " << player->getName() << "\t";
656 MutexAutoLock clientslock(m_clients_mutex);
657 RemoteClient* client = lockedGetClientNoEx(*i);
659 client->PrintInfo(infostream);
662 m_clients_names.push_back(player->getName());
667 void ClientInterface::send(u16 peer_id, u8 channelnum,
668 NetworkPacket* pkt, bool reliable)
670 m_con->Send(peer_id, channelnum, pkt, reliable);
673 void ClientInterface::sendToAll(u16 channelnum,
674 NetworkPacket* pkt, bool reliable)
676 MutexAutoLock clientslock(m_clients_mutex);
677 for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
678 i != m_clients.end(); ++i) {
679 RemoteClient *client = i->second;
681 if (client->net_proto_version != 0) {
682 m_con->Send(client->peer_id, channelnum, pkt, reliable);
687 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
689 MutexAutoLock clientslock(m_clients_mutex);
690 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
691 // The client may not exist; clients are immediately removed if their
692 // access is denied, and this event occurs later then.
693 if (n == m_clients.end())
696 if (n->second->getState() >= state_min)
702 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
704 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
705 // The client may not exist; clients are immediately removed if their
706 // access is denied, and this event occurs later then.
707 if (n == m_clients.end())
710 if (n->second->getState() >= state_min)
716 ClientState ClientInterface::getClientState(u16 peer_id)
718 MutexAutoLock clientslock(m_clients_mutex);
719 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
720 // The client may not exist; clients are immediately removed if their
721 // access is denied, and this event occurs later then.
722 if (n == m_clients.end())
725 return n->second->getState();
728 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
730 MutexAutoLock clientslock(m_clients_mutex);
731 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
732 // The client may not exist; clients are immediately removed if their
733 // access is denied, and this event occurs later then.
734 if (n != m_clients.end())
735 n->second->setName(name);
738 void ClientInterface::DeleteClient(u16 peer_id)
740 MutexAutoLock conlock(m_clients_mutex);
743 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
744 // The client may not exist; clients are immediately removed if their
745 // access is denied, and this event occurs later then.
746 if (n == m_clients.end())
750 Mark objects to be not known by the client
752 //TODO this should be done by client destructor!!!
753 RemoteClient *client = n->second;
755 for(std::set<u16>::iterator
756 i = client->m_known_objects.begin();
757 i != client->m_known_objects.end(); ++i)
761 ServerActiveObject* obj = m_env->getActiveObject(id);
763 if(obj && obj->m_known_by_count > 0)
764 obj->m_known_by_count--;
768 delete m_clients[peer_id];
769 m_clients.erase(peer_id);
772 void ClientInterface::CreateClient(u16 peer_id)
774 MutexAutoLock conlock(m_clients_mutex);
777 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
778 // The client shouldn't already exist
779 if (n != m_clients.end()) return;
782 RemoteClient *client = new RemoteClient();
783 client->peer_id = peer_id;
784 m_clients[client->peer_id] = client;
787 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
790 MutexAutoLock clientlock(m_clients_mutex);
793 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
795 // No client to deliver event
796 if (n == m_clients.end())
798 n->second->notifyEvent(event);
801 if ((event == CSE_SetClientReady) ||
802 (event == CSE_Disconnect) ||
803 (event == CSE_SetDenied))
809 u16 ClientInterface::getProtocolVersion(u16 peer_id)
811 MutexAutoLock conlock(m_clients_mutex);
814 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
816 // No client to get version
817 if (n == m_clients.end())
820 return n->second->net_proto_version;
823 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
825 MutexAutoLock conlock(m_clients_mutex);
828 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
830 // No client to set versions
831 if (n == m_clients.end())
834 n->second->setVersionInfo(major,minor,patch,full);