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.
21 #include "clientiface.h"
22 #include "network/connection.h"
23 #include "network/serveropcodes.h"
24 #include "remoteplayer.h"
27 #include "serverenvironment.h"
30 #include "content_sao.h" // TODO this is used for cleanup of only
33 #include "face_position_cache.h"
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)
70 m_nothing_to_send_pause_timer -= dtime;
71 m_nearest_unsent_reset_timer += dtime;
73 if(m_nothing_to_send_pause_timer >= 0)
76 RemotePlayer *player = env->getPlayer(peer_id);
77 // This can happen sometimes; clients and players are not in perfect sync.
81 PlayerSAO *sao = player->getPlayerSAO();
85 // Won't send anything if already sending
86 if(m_blocks_sending.size() >= g_settings->getU16
87 ("max_simultaneous_block_sends_per_client"))
89 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
93 v3f playerpos = sao->getBasePosition();
94 const v3f &playerspeed = player->getSpeed();
95 v3f playerspeeddir(0,0,0);
96 if(playerspeed.getLength() > 1.0*BS)
97 playerspeeddir = playerspeed / playerspeed.getLength();
98 // Predict to next block
99 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
101 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
103 v3s16 center = getNodeBlockPos(center_nodepos);
105 // Camera position and direction
106 v3f camera_pos = sao->getEyePosition();
107 v3f camera_dir = v3f(0,0,1);
108 camera_dir.rotateYZBy(sao->getPitch());
109 camera_dir.rotateXZBy(sao->getYaw());
111 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
112 <<camera_dir.Z<<")"<<std::endl;*/
115 Get the starting value of the block finder radius.
118 if(m_last_center != center)
120 m_nearest_unsent_d = 0;
121 m_last_center = center;
124 /*infostream<<"m_nearest_unsent_reset_timer="
125 <<m_nearest_unsent_reset_timer<<std::endl;*/
127 // Reset periodically to workaround for some bugs or stuff
128 if(m_nearest_unsent_reset_timer > 20.0)
130 m_nearest_unsent_reset_timer = 0;
131 m_nearest_unsent_d = 0;
132 //infostream<<"Resetting m_nearest_unsent_d for "
133 // <<server->getPlayerName(peer_id)<<std::endl;
136 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
137 s16 d_start = m_nearest_unsent_d;
139 //infostream<<"d_start="<<d_start<<std::endl;
141 u16 max_simul_sends_setting = g_settings->getU16
142 ("max_simultaneous_block_sends_per_client");
143 u16 max_simul_sends_usually = max_simul_sends_setting;
146 Check the time from last addNode/removeNode.
148 Decrease send rate if player is building stuff.
150 m_time_from_building += dtime;
151 if(m_time_from_building < g_settings->getFloat(
152 "full_block_send_enable_min_time_from_building"))
154 max_simul_sends_usually
155 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
159 Number of blocks sending + number of blocks selected for sending
161 u32 num_blocks_selected = m_blocks_sending.size();
164 next time d will be continued from the d from which the nearest
165 unsent block was found this time.
167 This is because not necessarily any of the blocks found this
168 time are actually sent.
170 s32 new_nearest_unsent_d = -1;
172 // get view range and camera fov from the client
173 s16 wanted_range = sao->getWantedRange();
174 float camera_fov = sao->getFov();
175 // if FOV, wanted_range are not available (old client), fall back to old default
176 if (wanted_range <= 0) wanted_range = 1000;
177 if (camera_fov <= 0) camera_fov = (72.0*M_PI/180) * 4./3.;
179 const s16 full_d_max = MYMIN(g_settings->getS16("max_block_send_distance"), wanted_range);
180 const s16 d_opt = MYMIN(g_settings->getS16("block_send_optimize_distance"), wanted_range);
181 const s16 d_blocks_in_sight = full_d_max * BS * MAP_BLOCKSIZE;
182 //infostream << "Fov from client " << camera_fov << " full_d_max " << full_d_max << std::endl;
184 s16 d_max = full_d_max;
185 s16 d_max_gen = MYMIN(g_settings->getS16("max_block_generate_distance"), wanted_range);
187 // Don't loop very much at a time
188 s16 max_d_increment_at_time = 2;
189 if(d_max > d_start + max_d_increment_at_time)
190 d_max = d_start + max_d_increment_at_time;
192 s32 nearest_emerged_d = -1;
193 s32 nearest_emergefull_d = -1;
194 s32 nearest_sent_d = -1;
195 //bool queue_is_full = false;
197 const v3s16 cam_pos_nodes = floatToInt(camera_pos, BS);
198 const bool occ_cull = g_settings->getBool("server_side_occlusion_culling");
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())
238 Do not go over max mapgen limit
240 if (blockpos_over_max_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.
253 if (!isBlockInSight(p, camera_pos, camera_dir, camera_fov, d_blocks_in_sight, &dist)) {
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;
275 // Reset usage timer, this block will be of use in the future.
276 block->resetUsageTimer();
278 // Block is dummy if data doesn't exist.
279 // It means it has been not found from disk and not generated
280 if (block->isDummy()) {
281 surely_not_found_on_disk = true;
284 if (!block->isGenerated())
285 block_is_invalid = true;
288 If block is not close, don't send it unless it is near
291 Block is near ground level if night-time mesh
292 differs from day-time mesh.
295 if (!block->getDayNightDiff())
299 if (occ_cull && !block_is_invalid &&
300 env->getMap().isBlockOccluded(block, cam_pos_nodes)) {
306 If block has been marked to not exist on disk (dummy)
307 and generating new ones is not wanted, skip block.
309 if (!generate && surely_not_found_on_disk) {
315 Add inexistent block to emerge queue.
317 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
319 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
320 if (nearest_emerged_d == -1)
321 nearest_emerged_d = d;
323 if (nearest_emergefull_d == -1)
324 nearest_emergefull_d = d;
325 goto queue_full_break;
332 if(nearest_sent_d == -1)
336 Add block to send queue
338 PrioritySortedBlockTransfer q((float)dist, p, peer_id);
342 num_blocks_selected += 1;
347 // If nothing was found for sending and nothing was queued for
348 // emerging, continue next time browsing from here
349 if(nearest_emerged_d != -1){
350 new_nearest_unsent_d = nearest_emerged_d;
351 } else if(nearest_emergefull_d != -1){
352 new_nearest_unsent_d = nearest_emergefull_d;
355 new_nearest_unsent_d = 0;
356 m_nothing_to_send_pause_timer = 2.0;
358 if(nearest_sent_d != -1)
359 new_nearest_unsent_d = nearest_sent_d;
361 new_nearest_unsent_d = d;
365 if(new_nearest_unsent_d != -1)
366 m_nearest_unsent_d = new_nearest_unsent_d;
369 void RemoteClient::GotBlock(v3s16 p)
371 if (m_blocks_modified.find(p) == m_blocks_modified.end()) {
372 if (m_blocks_sending.find(p) != m_blocks_sending.end())
373 m_blocks_sending.erase(p);
375 m_excess_gotblocks++;
377 m_blocks_sent.insert(p);
381 void RemoteClient::SentBlock(v3s16 p)
383 if (m_blocks_modified.find(p) != m_blocks_modified.end())
384 m_blocks_modified.erase(p);
386 if(m_blocks_sending.find(p) == m_blocks_sending.end())
387 m_blocks_sending[p] = 0.0;
389 infostream<<"RemoteClient::SentBlock(): Sent block"
390 " already in m_blocks_sending"<<std::endl;
393 void RemoteClient::SetBlockNotSent(v3s16 p)
395 m_nearest_unsent_d = 0;
396 m_nothing_to_send_pause_timer = 0;
398 if(m_blocks_sending.find(p) != m_blocks_sending.end())
399 m_blocks_sending.erase(p);
400 if(m_blocks_sent.find(p) != m_blocks_sent.end())
401 m_blocks_sent.erase(p);
402 m_blocks_modified.insert(p);
405 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
407 m_nearest_unsent_d = 0;
408 m_nothing_to_send_pause_timer = 0;
410 for (auto &block : blocks) {
411 v3s16 p = block.first;
412 m_blocks_modified.insert(p);
414 if(m_blocks_sending.find(p) != m_blocks_sending.end())
415 m_blocks_sending.erase(p);
416 if(m_blocks_sent.find(p) != m_blocks_sent.end())
417 m_blocks_sent.erase(p);
421 void RemoteClient::notifyEvent(ClientStateEvent event)
423 std::ostringstream myerror;
427 //intentionally do nothing
432 m_state = CS_HelloSent;
435 m_state = CS_AwaitingInit2;
438 m_state = CS_Disconnecting;
443 /* GotInit2 SetDefinitionsSent SetMediaSent */
445 myerror << "Created: Invalid client state transition! " << event;
446 throw ClientStateError(myerror.str());
450 /* don't do anything if in denied state */
456 m_state = CS_AwaitingInit2;
457 if ((chosen_mech == AUTH_MECHANISM_SRP)
458 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
459 srp_verifier_delete((SRPVerifier *) auth_data);
460 chosen_mech = AUTH_MECHANISM_NONE;
463 m_state = CS_Disconnecting;
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 myerror << "HelloSent: Invalid client state transition! " << event;
474 throw ClientStateError(myerror.str());
477 case CS_AwaitingInit2:
481 confirmSerializationVersion();
482 m_state = CS_InitDone;
485 m_state = CS_Disconnecting;
491 /* Init SetDefinitionsSent SetMediaSent */
493 myerror << "InitSent: Invalid client state transition! " << event;
494 throw ClientStateError(myerror.str());
501 case CSE_SetDefinitionsSent:
502 m_state = CS_DefinitionsSent;
505 m_state = CS_Disconnecting;
511 /* Init GotInit2 SetMediaSent */
513 myerror << "InitDone: Invalid client state transition! " << event;
514 throw ClientStateError(myerror.str());
517 case CS_DefinitionsSent:
520 case CSE_SetClientReady:
524 m_state = CS_Disconnecting;
529 /* Init GotInit2 SetDefinitionsSent */
531 myerror << "DefinitionsSent: Invalid client state transition! " << event;
532 throw ClientStateError(myerror.str());
542 m_state = CS_Disconnecting;
544 case CSE_SudoSuccess:
545 m_state = CS_SudoMode;
546 if ((chosen_mech == AUTH_MECHANISM_SRP)
547 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
548 srp_verifier_delete((SRPVerifier *) auth_data);
549 chosen_mech = AUTH_MECHANISM_NONE;
551 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
553 myerror << "Active: Invalid client state transition! " << event;
554 throw ClientStateError(myerror.str());
565 m_state = CS_Disconnecting;
571 myerror << "Active: Invalid client state transition! " << event;
572 throw ClientStateError(myerror.str());
576 case CS_Disconnecting:
577 /* we are already disconnecting */
582 u64 RemoteClient::uptime() const
584 return porting::getTimeS() - m_connection_time;
587 ClientInterface::ClientInterface(const std::shared_ptr<con::Connection> & con)
591 m_print_info_timer(0.0)
595 ClientInterface::~ClientInterface()
601 MutexAutoLock clientslock(m_clients_mutex);
603 for (auto &client_it : m_clients) {
605 delete client_it.second;
610 std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
612 std::vector<u16> reply;
613 MutexAutoLock clientslock(m_clients_mutex);
615 for (const auto &m_client : m_clients) {
616 if (m_client.second->getState() >= min_state)
617 reply.push_back(m_client.second->peer_id);
624 * Verify if user limit was reached.
625 * User limit count all clients from HelloSent state (MT protocol user) to Active state
626 * @return true if user limit was reached
628 bool ClientInterface::isUserLimitReached()
630 return getClientIDs(CS_HelloSent).size() >= g_settings->getU16("max_users");
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 (u16 i : clients) {
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.emplace_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(NetworkPacket *pkt)
681 MutexAutoLock clientslock(m_clients_mutex);
682 for (auto &client_it : m_clients) {
683 RemoteClient *client = client_it.second;
685 if (client->net_proto_version != 0) {
686 m_con->Send(client->peer_id,
687 clientCommandFactoryTable[pkt->getCommand()].channel, pkt,
688 clientCommandFactoryTable[pkt->getCommand()].reliable);
693 void ClientInterface::sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt,
696 MutexAutoLock clientslock(m_clients_mutex);
697 for (auto &client_it : m_clients) {
698 RemoteClient *client = client_it.second;
699 NetworkPacket *pkt_to_send = nullptr;
701 if (client->net_proto_version >= min_proto_ver) {
703 } else if (client->net_proto_version != 0) {
704 pkt_to_send = legacypkt;
706 warningstream << "Client with unhandled version to handle: '"
707 << client->net_proto_version << "'";
711 m_con->Send(client->peer_id,
712 clientCommandFactoryTable[pkt_to_send->getCommand()].channel,
714 clientCommandFactoryTable[pkt_to_send->getCommand()].reliable);
718 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
720 MutexAutoLock clientslock(m_clients_mutex);
721 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
722 // The client may not exist; clients are immediately removed if their
723 // access is denied, and this event occurs later then.
724 if (n == m_clients.end())
727 if (n->second->getState() >= state_min)
733 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
735 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
736 // The client may not exist; clients are immediately removed if their
737 // access is denied, and this event occurs later then.
738 if (n == m_clients.end())
741 if (n->second->getState() >= state_min)
747 ClientState ClientInterface::getClientState(u16 peer_id)
749 MutexAutoLock clientslock(m_clients_mutex);
750 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
751 // The client may not exist; clients are immediately removed if their
752 // access is denied, and this event occurs later then.
753 if (n == m_clients.end())
756 return n->second->getState();
759 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
761 MutexAutoLock clientslock(m_clients_mutex);
762 RemoteClientMap::iterator n = m_clients.find(peer_id);
763 // The client may not exist; clients are immediately removed if their
764 // access is denied, and this event occurs later then.
765 if (n != m_clients.end())
766 n->second->setName(name);
769 void ClientInterface::DeleteClient(u16 peer_id)
771 MutexAutoLock conlock(m_clients_mutex);
774 RemoteClientMap::iterator n = m_clients.find(peer_id);
775 // The client may not exist; clients are immediately removed if their
776 // access is denied, and this event occurs later then.
777 if (n == m_clients.end())
781 Mark objects to be not known by the client
783 //TODO this should be done by client destructor!!!
784 RemoteClient *client = n->second;
786 for (u16 id : client->m_known_objects) {
788 ServerActiveObject* obj = m_env->getActiveObject(id);
790 if(obj && obj->m_known_by_count > 0)
791 obj->m_known_by_count--;
795 delete m_clients[peer_id];
796 m_clients.erase(peer_id);
799 void ClientInterface::CreateClient(u16 peer_id)
801 MutexAutoLock conlock(m_clients_mutex);
804 RemoteClientMap::iterator n = m_clients.find(peer_id);
805 // The client shouldn't already exist
806 if (n != m_clients.end()) return;
809 RemoteClient *client = new RemoteClient();
810 client->peer_id = peer_id;
811 m_clients[client->peer_id] = client;
814 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
817 MutexAutoLock clientlock(m_clients_mutex);
820 RemoteClientMap::iterator n = m_clients.find(peer_id);
822 // No client to deliver event
823 if (n == m_clients.end())
825 n->second->notifyEvent(event);
828 if ((event == CSE_SetClientReady) ||
829 (event == CSE_Disconnect) ||
830 (event == CSE_SetDenied))
836 u16 ClientInterface::getProtocolVersion(u16 peer_id)
838 MutexAutoLock conlock(m_clients_mutex);
841 RemoteClientMap::iterator n = m_clients.find(peer_id);
843 // No client to get version
844 if (n == m_clients.end())
847 return n->second->net_proto_version;
850 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
852 MutexAutoLock conlock(m_clients_mutex);
855 RemoteClientMap::iterator n = m_clients.find(peer_id);
857 // No client to set versions
858 if (n == m_clients.end())
861 n->second->setVersionInfo(major,minor,patch,full);