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 "remoteplayer.h"
26 #include "network/connection.h"
27 #include "serverenvironment.h"
30 #include "content_sao.h" // TODO this is used for cleanup of only
32 #include "network/serveropcodes.h"
34 #include "face_position_cache.h"
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 // get view range and camera fov from the client
177 s16 wanted_range = sao->getWantedRange();
178 float camera_fov = sao->getFov();
179 // if FOV, wanted_range are not available (old client), fall back to old default
180 if (wanted_range <= 0) wanted_range = 1000;
181 if (camera_fov <= 0) camera_fov = (72.0*M_PI/180) * 4./3.;
183 const s16 full_d_max = MYMIN(g_settings->getS16("max_block_send_distance"), wanted_range);
184 const s16 d_opt = MYMIN(g_settings->getS16("block_send_optimize_distance"), wanted_range);
185 const s16 d_blocks_in_sight = full_d_max * BS * MAP_BLOCKSIZE;
186 //infostream << "Fov from client " << camera_fov << " full_d_max " << full_d_max << std::endl;
188 s16 d_max = full_d_max;
189 s16 d_max_gen = MYMIN(g_settings->getS16("max_block_generate_distance"), wanted_range);
191 // Don't loop very much at a time
192 s16 max_d_increment_at_time = 2;
193 if(d_max > d_start + max_d_increment_at_time)
194 d_max = d_start + max_d_increment_at_time;
196 s32 nearest_emerged_d = -1;
197 s32 nearest_emergefull_d = -1;
198 s32 nearest_sent_d = -1;
199 //bool queue_is_full = false;
201 const v3s16 cam_pos_nodes = floatToInt(camera_pos, BS);
202 const bool occ_cull = g_settings->getBool("server_side_occlusion_culling");
205 for(d = d_start; d <= d_max; d++) {
207 Get the border/face dot coordinates of a "d-radiused"
210 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
212 std::vector<v3s16>::iterator li;
213 for(li = list.begin(); li != list.end(); ++li) {
214 v3s16 p = *li + center;
218 - Don't allow too many simultaneous transfers
219 - EXCEPT when the blocks are very close
221 Also, don't send blocks that are already flying.
224 // Start with the usual maximum
225 u16 max_simul_dynamic = max_simul_sends_usually;
227 // If block is very close, allow full maximum
228 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
229 max_simul_dynamic = max_simul_sends_setting;
231 // Don't select too many blocks for sending
232 if (num_blocks_selected >= max_simul_dynamic) {
233 //queue_is_full = true;
234 goto queue_full_break;
237 // Don't send blocks that are currently being transferred
238 if (m_blocks_sending.find(p) != m_blocks_sending.end())
242 Do not go over max mapgen limit
244 if (blockpos_over_max_limit(p))
247 // If this is true, inexistent block will be made from scratch
248 bool generate = d <= d_max_gen;
251 Don't generate or send if not in sight
252 FIXME This only works if the client uses a small enough
253 FOV setting. The default of 72 degrees is fine.
257 if (!isBlockInSight(p, camera_pos, camera_dir, camera_fov, d_blocks_in_sight, &dist)) {
262 Don't send already sent blocks
265 if(m_blocks_sent.find(p) != m_blocks_sent.end())
272 Check if map has this block
274 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
276 bool surely_not_found_on_disk = false;
277 bool block_is_invalid = false;
279 // Reset usage timer, this block will be of use in the future.
280 block->resetUsageTimer();
282 // Block is dummy if data doesn't exist.
283 // It means it has been not found from disk and not generated
286 surely_not_found_on_disk = true;
289 if(block->isGenerated() == false)
290 block_is_invalid = true;
293 If block is not close, don't send it unless it is near
296 Block is near ground level if night-time mesh
297 differs from day-time mesh.
301 if(block->getDayNightDiff() == false)
305 if (occ_cull && !block_is_invalid &&
306 env->getMap().isBlockOccluded(block, cam_pos_nodes)) {
312 If block has been marked to not exist on disk (dummy)
313 and generating new ones is not wanted, skip block.
315 if(generate == false && surely_not_found_on_disk == true)
322 Add inexistent block to emerge queue.
324 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
326 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
327 if (nearest_emerged_d == -1)
328 nearest_emerged_d = d;
330 if (nearest_emergefull_d == -1)
331 nearest_emergefull_d = d;
332 goto queue_full_break;
339 if(nearest_sent_d == -1)
343 Add block to send queue
345 PrioritySortedBlockTransfer q((float)dist, p, peer_id);
349 num_blocks_selected += 1;
354 // If nothing was found for sending and nothing was queued for
355 // emerging, continue next time browsing from here
356 if(nearest_emerged_d != -1){
357 new_nearest_unsent_d = nearest_emerged_d;
358 } else if(nearest_emergefull_d != -1){
359 new_nearest_unsent_d = nearest_emergefull_d;
362 new_nearest_unsent_d = 0;
363 m_nothing_to_send_pause_timer = 2.0;
365 if(nearest_sent_d != -1)
366 new_nearest_unsent_d = nearest_sent_d;
368 new_nearest_unsent_d = d;
372 if(new_nearest_unsent_d != -1)
373 m_nearest_unsent_d = new_nearest_unsent_d;
376 void RemoteClient::GotBlock(v3s16 p)
378 if (m_blocks_modified.find(p) == m_blocks_modified.end()) {
379 if (m_blocks_sending.find(p) != m_blocks_sending.end())
380 m_blocks_sending.erase(p);
382 m_excess_gotblocks++;
384 m_blocks_sent.insert(p);
388 void RemoteClient::SentBlock(v3s16 p)
390 if (m_blocks_modified.find(p) != m_blocks_modified.end())
391 m_blocks_modified.erase(p);
393 if(m_blocks_sending.find(p) == m_blocks_sending.end())
394 m_blocks_sending[p] = 0.0;
396 infostream<<"RemoteClient::SentBlock(): Sent block"
397 " already in m_blocks_sending"<<std::endl;
400 void RemoteClient::SetBlockNotSent(v3s16 p)
402 m_nearest_unsent_d = 0;
403 m_nothing_to_send_pause_timer = 0;
405 if(m_blocks_sending.find(p) != m_blocks_sending.end())
406 m_blocks_sending.erase(p);
407 if(m_blocks_sent.find(p) != m_blocks_sent.end())
408 m_blocks_sent.erase(p);
409 m_blocks_modified.insert(p);
412 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
414 m_nearest_unsent_d = 0;
415 m_nothing_to_send_pause_timer = 0;
417 for(std::map<v3s16, MapBlock*>::iterator
419 i != blocks.end(); ++i)
422 m_blocks_modified.insert(p);
424 if(m_blocks_sending.find(p) != m_blocks_sending.end())
425 m_blocks_sending.erase(p);
426 if(m_blocks_sent.find(p) != m_blocks_sent.end())
427 m_blocks_sent.erase(p);
431 void RemoteClient::notifyEvent(ClientStateEvent event)
433 std::ostringstream myerror;
437 //intentionally do nothing
442 m_state = CS_HelloSent;
445 m_state = CS_AwaitingInit2;
448 m_state = CS_Disconnecting;
453 /* GotInit2 SetDefinitionsSent SetMediaSent */
455 myerror << "Created: Invalid client state transition! " << event;
456 throw ClientStateError(myerror.str());
460 /* don't do anything if in denied state */
466 m_state = CS_AwaitingInit2;
467 if ((chosen_mech == AUTH_MECHANISM_SRP)
468 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
469 srp_verifier_delete((SRPVerifier *) auth_data);
470 chosen_mech = AUTH_MECHANISM_NONE;
473 m_state = CS_Disconnecting;
477 if ((chosen_mech == AUTH_MECHANISM_SRP)
478 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
479 srp_verifier_delete((SRPVerifier *) auth_data);
480 chosen_mech = AUTH_MECHANISM_NONE;
483 myerror << "HelloSent: Invalid client state transition! " << event;
484 throw ClientStateError(myerror.str());
487 case CS_AwaitingInit2:
491 confirmSerializationVersion();
492 m_state = CS_InitDone;
495 m_state = CS_Disconnecting;
501 /* Init SetDefinitionsSent SetMediaSent */
503 myerror << "InitSent: Invalid client state transition! " << event;
504 throw ClientStateError(myerror.str());
511 case CSE_SetDefinitionsSent:
512 m_state = CS_DefinitionsSent;
515 m_state = CS_Disconnecting;
521 /* Init GotInit2 SetMediaSent */
523 myerror << "InitDone: Invalid client state transition! " << event;
524 throw ClientStateError(myerror.str());
527 case CS_DefinitionsSent:
530 case CSE_SetClientReady:
534 m_state = CS_Disconnecting;
539 /* Init GotInit2 SetDefinitionsSent */
541 myerror << "DefinitionsSent: Invalid client state transition! " << event;
542 throw ClientStateError(myerror.str());
552 m_state = CS_Disconnecting;
554 case CSE_SudoSuccess:
555 m_state = CS_SudoMode;
556 if ((chosen_mech == AUTH_MECHANISM_SRP)
557 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
558 srp_verifier_delete((SRPVerifier *) auth_data);
559 chosen_mech = AUTH_MECHANISM_NONE;
561 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
563 myerror << "Active: Invalid client state transition! " << event;
564 throw ClientStateError(myerror.str());
575 m_state = CS_Disconnecting;
581 myerror << "Active: Invalid client state transition! " << event;
582 throw ClientStateError(myerror.str());
586 case CS_Disconnecting:
587 /* we are already disconnecting */
592 u64 RemoteClient::uptime() const
594 return porting::getTimeS() - m_connection_time;
597 ClientInterface::ClientInterface(con::Connection* con)
601 m_print_info_timer(0.0)
605 ClientInterface::~ClientInterface()
611 MutexAutoLock clientslock(m_clients_mutex);
613 for (RemoteClientMap::iterator i = m_clients.begin();
614 i != m_clients.end(); ++i) {
621 std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
623 std::vector<u16> reply;
624 MutexAutoLock clientslock(m_clients_mutex);
626 for (RemoteClientMap::iterator i = m_clients.begin();
627 i != m_clients.end(); ++i) {
628 if (i->second->getState() >= min_state)
629 reply.push_back(i->second->peer_id);
635 void ClientInterface::step(float dtime)
637 m_print_info_timer += dtime;
638 if(m_print_info_timer >= 30.0)
640 m_print_info_timer = 0.0;
645 void ClientInterface::UpdatePlayerList()
648 std::vector<u16> clients = getClientIDs();
649 m_clients_names.clear();
653 infostream<<"Players:"<<std::endl;
655 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
656 RemotePlayer *player = m_env->getPlayer(*i);
661 infostream << "* " << player->getName() << "\t";
664 MutexAutoLock clientslock(m_clients_mutex);
665 RemoteClient* client = lockedGetClientNoEx(*i);
667 client->PrintInfo(infostream);
670 m_clients_names.push_back(player->getName());
675 void ClientInterface::send(u16 peer_id, u8 channelnum,
676 NetworkPacket* pkt, bool reliable)
678 m_con->Send(peer_id, channelnum, pkt, reliable);
681 void ClientInterface::sendToAll(NetworkPacket *pkt)
683 MutexAutoLock clientslock(m_clients_mutex);
684 for (RemoteClientMap::iterator i = m_clients.begin();
685 i != m_clients.end(); ++i) {
686 RemoteClient *client = i->second;
688 if (client->net_proto_version != 0) {
689 m_con->Send(client->peer_id,
690 clientCommandFactoryTable[pkt->getCommand()].channel, pkt,
691 clientCommandFactoryTable[pkt->getCommand()].reliable);
696 void ClientInterface::sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt,
699 MutexAutoLock clientslock(m_clients_mutex);
700 for (std::unordered_map<u16, RemoteClient*>::iterator i = m_clients.begin();
701 i != m_clients.end(); ++i) {
702 RemoteClient *client = i->second;
703 NetworkPacket *pkt_to_send = nullptr;
705 if (client->net_proto_version >= min_proto_ver) {
707 } else if (client->net_proto_version != 0) {
708 pkt_to_send = legacypkt;
710 warningstream << "Client with unhandled version to handle: '"
711 << client->net_proto_version << "'";
715 m_con->Send(client->peer_id,
716 clientCommandFactoryTable[pkt_to_send->getCommand()].channel,
718 clientCommandFactoryTable[pkt_to_send->getCommand()].reliable);
722 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
724 MutexAutoLock clientslock(m_clients_mutex);
725 RemoteClientMap::const_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 if (n->second->getState() >= state_min)
737 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
739 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
740 // The client may not exist; clients are immediately removed if their
741 // access is denied, and this event occurs later then.
742 if (n == m_clients.end())
745 if (n->second->getState() >= state_min)
751 ClientState ClientInterface::getClientState(u16 peer_id)
753 MutexAutoLock clientslock(m_clients_mutex);
754 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
755 // The client may not exist; clients are immediately removed if their
756 // access is denied, and this event occurs later then.
757 if (n == m_clients.end())
760 return n->second->getState();
763 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
765 MutexAutoLock clientslock(m_clients_mutex);
766 RemoteClientMap::iterator n = m_clients.find(peer_id);
767 // The client may not exist; clients are immediately removed if their
768 // access is denied, and this event occurs later then.
769 if (n != m_clients.end())
770 n->second->setName(name);
773 void ClientInterface::DeleteClient(u16 peer_id)
775 MutexAutoLock conlock(m_clients_mutex);
778 RemoteClientMap::iterator n = m_clients.find(peer_id);
779 // The client may not exist; clients are immediately removed if their
780 // access is denied, and this event occurs later then.
781 if (n == m_clients.end())
785 Mark objects to be not known by the client
787 //TODO this should be done by client destructor!!!
788 RemoteClient *client = n->second;
790 for (std::set<u16>::iterator i = client->m_known_objects.begin();
791 i != client->m_known_objects.end(); ++i) {
794 ServerActiveObject* obj = m_env->getActiveObject(id);
796 if(obj && obj->m_known_by_count > 0)
797 obj->m_known_by_count--;
801 delete m_clients[peer_id];
802 m_clients.erase(peer_id);
805 void ClientInterface::CreateClient(u16 peer_id)
807 MutexAutoLock conlock(m_clients_mutex);
810 RemoteClientMap::iterator n = m_clients.find(peer_id);
811 // The client shouldn't already exist
812 if (n != m_clients.end()) return;
815 RemoteClient *client = new RemoteClient();
816 client->peer_id = peer_id;
817 m_clients[client->peer_id] = client;
820 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
823 MutexAutoLock clientlock(m_clients_mutex);
826 RemoteClientMap::iterator n = m_clients.find(peer_id);
828 // No client to deliver event
829 if (n == m_clients.end())
831 n->second->notifyEvent(event);
834 if ((event == CSE_SetClientReady) ||
835 (event == CSE_Disconnect) ||
836 (event == CSE_SetDenied))
842 u16 ClientInterface::getProtocolVersion(u16 peer_id)
844 MutexAutoLock conlock(m_clients_mutex);
847 RemoteClientMap::iterator n = m_clients.find(peer_id);
849 // No client to get version
850 if (n == m_clients.end())
853 return n->second->net_proto_version;
856 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
858 MutexAutoLock conlock(m_clients_mutex);
861 RemoteClientMap::iterator n = m_clients.find(peer_id);
863 // No client to set versions
864 if (n == m_clients.end())
867 n->second->setVersionInfo(major,minor,patch,full);