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 "remoteplayer.h"
27 #include "network/connection.h"
28 #include "serverenvironment.h"
31 #include "content_sao.h" // TODO this is used for cleanup of only
35 const char *ClientInterface::statenames[] = {
50 std::string ClientInterface::state2Name(ClientState state)
52 return statenames[state];
55 void RemoteClient::ResendBlockIfOnWire(v3s16 p)
57 // if this block is on wire, mark it for sending again as soon as possible
58 if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
63 void RemoteClient::GetNextBlocks (
64 ServerEnvironment *env,
65 EmergeManager * emerge,
67 std::vector<PrioritySortedBlockTransfer> &dest)
69 DSTACK(FUNCTION_NAME);
73 m_nothing_to_send_pause_timer -= dtime;
74 m_nearest_unsent_reset_timer += dtime;
76 if(m_nothing_to_send_pause_timer >= 0)
79 RemotePlayer *player = env->getPlayer(peer_id);
80 // This can happen sometimes; clients and players are not in perfect sync.
84 PlayerSAO *sao = player->getPlayerSAO();
88 // Won't send anything if already sending
89 if(m_blocks_sending.size() >= g_settings->getU16
90 ("max_simultaneous_block_sends_per_client"))
92 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
96 v3f playerpos = sao->getBasePosition();
97 v3f playerspeed = player->getSpeed();
98 v3f playerspeeddir(0,0,0);
99 if(playerspeed.getLength() > 1.0*BS)
100 playerspeeddir = playerspeed / playerspeed.getLength();
101 // Predict to next block
102 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
104 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
106 v3s16 center = getNodeBlockPos(center_nodepos);
108 // Camera position and direction
109 v3f camera_pos = sao->getEyePosition();
110 v3f camera_dir = v3f(0,0,1);
111 camera_dir.rotateYZBy(sao->getPitch());
112 camera_dir.rotateXZBy(sao->getYaw());
114 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
115 <<camera_dir.Z<<")"<<std::endl;*/
118 Get the starting value of the block finder radius.
121 if(m_last_center != center)
123 m_nearest_unsent_d = 0;
124 m_last_center = center;
127 /*infostream<<"m_nearest_unsent_reset_timer="
128 <<m_nearest_unsent_reset_timer<<std::endl;*/
130 // Reset periodically to workaround for some bugs or stuff
131 if(m_nearest_unsent_reset_timer > 20.0)
133 m_nearest_unsent_reset_timer = 0;
134 m_nearest_unsent_d = 0;
135 //infostream<<"Resetting m_nearest_unsent_d for "
136 // <<server->getPlayerName(peer_id)<<std::endl;
139 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
140 s16 d_start = m_nearest_unsent_d;
142 //infostream<<"d_start="<<d_start<<std::endl;
144 u16 max_simul_sends_setting = g_settings->getU16
145 ("max_simultaneous_block_sends_per_client");
146 u16 max_simul_sends_usually = max_simul_sends_setting;
149 Check the time from last addNode/removeNode.
151 Decrease send rate if player is building stuff.
153 m_time_from_building += dtime;
154 if(m_time_from_building < g_settings->getFloat(
155 "full_block_send_enable_min_time_from_building"))
157 max_simul_sends_usually
158 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
162 Number of blocks sending + number of blocks selected for sending
164 u32 num_blocks_selected = m_blocks_sending.size();
167 next time d will be continued from the d from which the nearest
168 unsent block was found this time.
170 This is because not necessarily any of the blocks found this
171 time are actually sent.
173 s32 new_nearest_unsent_d = -1;
175 // get view range and camera fov from the client
176 s16 wanted_range = sao->getWantedRange();
177 float camera_fov = sao->getFov();
178 // if FOV, wanted_range are not available (old client), fall back to old default
179 if (wanted_range <= 0) wanted_range = 1000;
180 if (camera_fov <= 0) camera_fov = (72.0*M_PI/180) * 4./3.;
182 const s16 full_d_max = MYMIN(g_settings->getS16("max_block_send_distance"), wanted_range);
183 const s16 d_opt = MYMIN(g_settings->getS16("block_send_optimize_distance"), wanted_range);
184 const s16 d_blocks_in_sight = full_d_max * BS * MAP_BLOCKSIZE;
185 //infostream << "Fov from client " << camera_fov << " full_d_max " << full_d_max << std::endl;
187 s16 d_max = full_d_max;
188 s16 d_max_gen = MYMIN(g_settings->getS16("max_block_generate_distance"), wanted_range);
190 // Don't loop very much at a time
191 s16 max_d_increment_at_time = 2;
192 if(d_max > d_start + max_d_increment_at_time)
193 d_max = d_start + max_d_increment_at_time;
195 s32 nearest_emerged_d = -1;
196 s32 nearest_emergefull_d = -1;
197 s32 nearest_sent_d = -1;
198 //bool queue_is_full = false;
201 for(d = d_start; d <= d_max; d++) {
203 Get the border/face dot coordinates of a "d-radiused"
206 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
208 std::vector<v3s16>::iterator li;
209 for(li = list.begin(); li != list.end(); ++li) {
210 v3s16 p = *li + center;
214 - Don't allow too many simultaneous transfers
215 - EXCEPT when the blocks are very close
217 Also, don't send blocks that are already flying.
220 // Start with the usual maximum
221 u16 max_simul_dynamic = max_simul_sends_usually;
223 // If block is very close, allow full maximum
224 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
225 max_simul_dynamic = max_simul_sends_setting;
227 // Don't select too many blocks for sending
228 if (num_blocks_selected >= max_simul_dynamic) {
229 //queue_is_full = true;
230 goto queue_full_break;
233 // Don't send blocks that are currently being transferred
234 if (m_blocks_sending.find(p) != m_blocks_sending.end())
240 if (blockpos_over_limit(p))
243 // If this is true, inexistent block will be made from scratch
244 bool generate = d <= d_max_gen;
247 Don't generate or send if not in sight
248 FIXME This only works if the client uses a small enough
249 FOV setting. The default of 72 degrees is fine.
252 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, d_blocks_in_sight) == false)
258 Don't send already sent blocks
261 if(m_blocks_sent.find(p) != m_blocks_sent.end())
268 Check if map has this block
270 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
272 bool surely_not_found_on_disk = false;
273 bool block_is_invalid = false;
276 // Reset usage timer, this block will be of use in the future.
277 block->resetUsageTimer();
279 // Block is dummy if data doesn't exist.
280 // It means it has been not found from disk and not generated
283 surely_not_found_on_disk = true;
286 // Block is valid if lighting is up-to-date and data exists
287 if(block->isValid() == false)
289 block_is_invalid = true;
292 if(block->isGenerated() == false)
293 block_is_invalid = true;
296 If block is not close, don't send it unless it is near
299 Block is near ground level if night-time mesh
300 differs from day-time mesh.
304 if(block->getDayNightDiff() == false)
310 If block has been marked to not exist on disk (dummy)
311 and generating new ones is not wanted, skip block.
313 if(generate == false && surely_not_found_on_disk == true)
320 Add inexistent block to emerge queue.
322 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
324 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
325 if (nearest_emerged_d == -1)
326 nearest_emerged_d = d;
328 if (nearest_emergefull_d == -1)
329 nearest_emergefull_d = d;
330 goto queue_full_break;
337 if(nearest_sent_d == -1)
341 Add block to send queue
343 PrioritySortedBlockTransfer q((float)d, p, peer_id);
347 num_blocks_selected += 1;
352 // If nothing was found for sending and nothing was queued for
353 // emerging, continue next time browsing from here
354 if(nearest_emerged_d != -1){
355 new_nearest_unsent_d = nearest_emerged_d;
356 } else if(nearest_emergefull_d != -1){
357 new_nearest_unsent_d = nearest_emergefull_d;
360 new_nearest_unsent_d = 0;
361 m_nothing_to_send_pause_timer = 2.0;
363 if(nearest_sent_d != -1)
364 new_nearest_unsent_d = nearest_sent_d;
366 new_nearest_unsent_d = d;
370 if(new_nearest_unsent_d != -1)
371 m_nearest_unsent_d = new_nearest_unsent_d;
374 void RemoteClient::GotBlock(v3s16 p)
376 if (m_blocks_modified.find(p) == m_blocks_modified.end()) {
377 if (m_blocks_sending.find(p) != m_blocks_sending.end())
378 m_blocks_sending.erase(p);
380 m_excess_gotblocks++;
382 m_blocks_sent.insert(p);
386 void RemoteClient::SentBlock(v3s16 p)
388 if (m_blocks_modified.find(p) != m_blocks_modified.end())
389 m_blocks_modified.erase(p);
391 if(m_blocks_sending.find(p) == m_blocks_sending.end())
392 m_blocks_sending[p] = 0.0;
394 infostream<<"RemoteClient::SentBlock(): Sent block"
395 " already in m_blocks_sending"<<std::endl;
398 void RemoteClient::SetBlockNotSent(v3s16 p)
400 m_nearest_unsent_d = 0;
401 m_nothing_to_send_pause_timer = 0;
403 if(m_blocks_sending.find(p) != m_blocks_sending.end())
404 m_blocks_sending.erase(p);
405 if(m_blocks_sent.find(p) != m_blocks_sent.end())
406 m_blocks_sent.erase(p);
407 m_blocks_modified.insert(p);
410 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
412 m_nearest_unsent_d = 0;
413 m_nothing_to_send_pause_timer = 0;
415 for(std::map<v3s16, MapBlock*>::iterator
417 i != blocks.end(); ++i)
420 m_blocks_modified.insert(p);
422 if(m_blocks_sending.find(p) != m_blocks_sending.end())
423 m_blocks_sending.erase(p);
424 if(m_blocks_sent.find(p) != m_blocks_sent.end())
425 m_blocks_sent.erase(p);
429 void RemoteClient::notifyEvent(ClientStateEvent event)
431 std::ostringstream myerror;
435 //intentionally do nothing
440 m_state = CS_HelloSent;
443 m_state = CS_AwaitingInit2;
446 m_state = CS_Disconnecting;
451 /* GotInit2 SetDefinitionsSent SetMediaSent */
453 myerror << "Created: Invalid client state transition! " << event;
454 throw ClientStateError(myerror.str());
458 /* don't do anything if in denied state */
464 m_state = CS_AwaitingInit2;
465 if ((chosen_mech == AUTH_MECHANISM_SRP)
466 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
467 srp_verifier_delete((SRPVerifier *) auth_data);
468 chosen_mech = AUTH_MECHANISM_NONE;
471 m_state = CS_Disconnecting;
475 if ((chosen_mech == AUTH_MECHANISM_SRP)
476 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
477 srp_verifier_delete((SRPVerifier *) auth_data);
478 chosen_mech = AUTH_MECHANISM_NONE;
481 myerror << "HelloSent: Invalid client state transition! " << event;
482 throw ClientStateError(myerror.str());
485 case CS_AwaitingInit2:
489 confirmSerializationVersion();
490 m_state = CS_InitDone;
493 m_state = CS_Disconnecting;
499 /* Init SetDefinitionsSent SetMediaSent */
501 myerror << "InitSent: Invalid client state transition! " << event;
502 throw ClientStateError(myerror.str());
509 case CSE_SetDefinitionsSent:
510 m_state = CS_DefinitionsSent;
513 m_state = CS_Disconnecting;
519 /* Init GotInit2 SetMediaSent */
521 myerror << "InitDone: Invalid client state transition! " << event;
522 throw ClientStateError(myerror.str());
525 case CS_DefinitionsSent:
528 case CSE_SetClientReady:
532 m_state = CS_Disconnecting;
537 /* Init GotInit2 SetDefinitionsSent */
539 myerror << "DefinitionsSent: Invalid client state transition! " << event;
540 throw ClientStateError(myerror.str());
550 m_state = CS_Disconnecting;
552 case CSE_SudoSuccess:
553 m_state = CS_SudoMode;
554 if ((chosen_mech == AUTH_MECHANISM_SRP)
555 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
556 srp_verifier_delete((SRPVerifier *) auth_data);
557 chosen_mech = AUTH_MECHANISM_NONE;
559 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
561 myerror << "Active: Invalid client state transition! " << event;
562 throw ClientStateError(myerror.str());
573 m_state = CS_Disconnecting;
579 myerror << "Active: Invalid client state transition! " << event;
580 throw ClientStateError(myerror.str());
584 case CS_Disconnecting:
585 /* we are already disconnecting */
590 u32 RemoteClient::uptime()
592 return getTime(PRECISION_SECONDS) - m_connection_time;
595 ClientInterface::ClientInterface(con::Connection* con)
599 m_print_info_timer(0.0)
603 ClientInterface::~ClientInterface()
609 MutexAutoLock clientslock(m_clients_mutex);
611 for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
612 i != m_clients.end(); ++i) {
619 std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
621 std::vector<u16> reply;
622 MutexAutoLock clientslock(m_clients_mutex);
624 for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
625 i != m_clients.end(); ++i) {
626 if (i->second->getState() >= min_state)
627 reply.push_back(i->second->peer_id);
633 void ClientInterface::step(float dtime)
635 m_print_info_timer += dtime;
636 if(m_print_info_timer >= 30.0)
638 m_print_info_timer = 0.0;
643 void ClientInterface::UpdatePlayerList()
646 std::vector<u16> clients = getClientIDs();
647 m_clients_names.clear();
651 infostream<<"Players:"<<std::endl;
653 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
654 RemotePlayer *player = m_env->getPlayer(*i);
659 infostream << "* " << player->getName() << "\t";
662 MutexAutoLock clientslock(m_clients_mutex);
663 RemoteClient* client = lockedGetClientNoEx(*i);
665 client->PrintInfo(infostream);
668 m_clients_names.push_back(player->getName());
673 void ClientInterface::send(u16 peer_id, u8 channelnum,
674 NetworkPacket* pkt, bool reliable)
676 m_con->Send(peer_id, channelnum, pkt, reliable);
679 void ClientInterface::sendToAll(u16 channelnum,
680 NetworkPacket* pkt, bool reliable)
682 MutexAutoLock clientslock(m_clients_mutex);
683 for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
684 i != m_clients.end(); ++i) {
685 RemoteClient *client = i->second;
687 if (client->net_proto_version != 0) {
688 m_con->Send(client->peer_id, channelnum, pkt, reliable);
693 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
695 MutexAutoLock clientslock(m_clients_mutex);
696 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
697 // The client may not exist; clients are immediately removed if their
698 // access is denied, and this event occurs later then.
699 if (n == m_clients.end())
702 if (n->second->getState() >= state_min)
708 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
710 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
711 // The client may not exist; clients are immediately removed if their
712 // access is denied, and this event occurs later then.
713 if (n == m_clients.end())
716 if (n->second->getState() >= state_min)
722 ClientState ClientInterface::getClientState(u16 peer_id)
724 MutexAutoLock clientslock(m_clients_mutex);
725 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
726 // The client may not exist; clients are immediately removed if their
727 // access is denied, and this event occurs later then.
728 if (n == m_clients.end())
731 return n->second->getState();
734 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
736 MutexAutoLock clientslock(m_clients_mutex);
737 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
738 // The client may not exist; clients are immediately removed if their
739 // access is denied, and this event occurs later then.
740 if (n != m_clients.end())
741 n->second->setName(name);
744 void ClientInterface::DeleteClient(u16 peer_id)
746 MutexAutoLock conlock(m_clients_mutex);
749 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
750 // The client may not exist; clients are immediately removed if their
751 // access is denied, and this event occurs later then.
752 if (n == m_clients.end())
756 Mark objects to be not known by the client
758 //TODO this should be done by client destructor!!!
759 RemoteClient *client = n->second;
761 for(std::set<u16>::iterator
762 i = client->m_known_objects.begin();
763 i != client->m_known_objects.end(); ++i)
767 ServerActiveObject* obj = m_env->getActiveObject(id);
769 if(obj && obj->m_known_by_count > 0)
770 obj->m_known_by_count--;
774 delete m_clients[peer_id];
775 m_clients.erase(peer_id);
778 void ClientInterface::CreateClient(u16 peer_id)
780 MutexAutoLock conlock(m_clients_mutex);
783 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
784 // The client shouldn't already exist
785 if (n != m_clients.end()) return;
788 RemoteClient *client = new RemoteClient();
789 client->peer_id = peer_id;
790 m_clients[client->peer_id] = client;
793 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
796 MutexAutoLock clientlock(m_clients_mutex);
799 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
801 // No client to deliver event
802 if (n == m_clients.end())
804 n->second->notifyEvent(event);
807 if ((event == CSE_SetClientReady) ||
808 (event == CSE_Disconnect) ||
809 (event == CSE_SetDenied))
815 u16 ClientInterface::getProtocolVersion(u16 peer_id)
817 MutexAutoLock conlock(m_clients_mutex);
820 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
822 // No client to get version
823 if (n == m_clients.end())
826 return n->second->net_proto_version;
829 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
831 MutexAutoLock conlock(m_clients_mutex);
834 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
836 // No client to set versions
837 if (n == m_clients.end())
840 n->second->setVersionInfo(major,minor,patch,full);