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)
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 const 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;
200 const v3s16 cam_pos_nodes = floatToInt(camera_pos, BS);
201 const bool occ_cull = g_settings->getBool("server_side_occlusion_culling");
204 for(d = d_start; d <= d_max; d++) {
206 Get the border/face dot coordinates of a "d-radiused"
209 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
211 std::vector<v3s16>::iterator li;
212 for(li = list.begin(); li != list.end(); ++li) {
213 v3s16 p = *li + center;
217 - Don't allow too many simultaneous transfers
218 - EXCEPT when the blocks are very close
220 Also, don't send blocks that are already flying.
223 // Start with the usual maximum
224 u16 max_simul_dynamic = max_simul_sends_usually;
226 // If block is very close, allow full maximum
227 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
228 max_simul_dynamic = max_simul_sends_setting;
230 // Don't select too many blocks for sending
231 if (num_blocks_selected >= max_simul_dynamic) {
232 //queue_is_full = true;
233 goto queue_full_break;
236 // Don't send blocks that are currently being transferred
237 if (m_blocks_sending.find(p) != m_blocks_sending.end())
241 Do not go over max mapgen limit
243 if (blockpos_over_max_limit(p))
246 // If this is true, inexistent block will be made from scratch
247 bool generate = d <= d_max_gen;
250 Don't generate or send if not in sight
251 FIXME This only works if the client uses a small enough
252 FOV setting. The default of 72 degrees is fine.
256 if (!isBlockInSight(p, camera_pos, camera_dir, camera_fov, d_blocks_in_sight, &dist)) {
261 Don't send already sent blocks
264 if(m_blocks_sent.find(p) != m_blocks_sent.end())
271 Check if map has this block
273 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
275 bool surely_not_found_on_disk = false;
276 bool block_is_invalid = false;
278 // Reset usage timer, this block will be of use in the future.
279 block->resetUsageTimer();
281 // Block is dummy if data doesn't exist.
282 // It means it has been not found from disk and not generated
283 if (block->isDummy()) {
284 surely_not_found_on_disk = true;
287 if (!block->isGenerated())
288 block_is_invalid = true;
291 If block is not close, don't send it unless it is near
294 Block is near ground level if night-time mesh
295 differs from day-time mesh.
298 if (!block->getDayNightDiff())
302 if (occ_cull && !block_is_invalid &&
303 env->getMap().isBlockOccluded(block, cam_pos_nodes)) {
309 If block has been marked to not exist on disk (dummy)
310 and generating new ones is not wanted, skip block.
312 if (!generate && surely_not_found_on_disk) {
318 Add inexistent block to emerge queue.
320 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
322 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
323 if (nearest_emerged_d == -1)
324 nearest_emerged_d = d;
326 if (nearest_emergefull_d == -1)
327 nearest_emergefull_d = d;
328 goto queue_full_break;
335 if(nearest_sent_d == -1)
339 Add block to send queue
341 PrioritySortedBlockTransfer q((float)dist, p, peer_id);
345 num_blocks_selected += 1;
350 // If nothing was found for sending and nothing was queued for
351 // emerging, continue next time browsing from here
352 if(nearest_emerged_d != -1){
353 new_nearest_unsent_d = nearest_emerged_d;
354 } else if(nearest_emergefull_d != -1){
355 new_nearest_unsent_d = nearest_emergefull_d;
358 new_nearest_unsent_d = 0;
359 m_nothing_to_send_pause_timer = 2.0;
361 if(nearest_sent_d != -1)
362 new_nearest_unsent_d = nearest_sent_d;
364 new_nearest_unsent_d = d;
368 if(new_nearest_unsent_d != -1)
369 m_nearest_unsent_d = new_nearest_unsent_d;
372 void RemoteClient::GotBlock(v3s16 p)
374 if (m_blocks_modified.find(p) == m_blocks_modified.end()) {
375 if (m_blocks_sending.find(p) != m_blocks_sending.end())
376 m_blocks_sending.erase(p);
378 m_excess_gotblocks++;
380 m_blocks_sent.insert(p);
384 void RemoteClient::SentBlock(v3s16 p)
386 if (m_blocks_modified.find(p) != m_blocks_modified.end())
387 m_blocks_modified.erase(p);
389 if(m_blocks_sending.find(p) == m_blocks_sending.end())
390 m_blocks_sending[p] = 0.0;
392 infostream<<"RemoteClient::SentBlock(): Sent block"
393 " already in m_blocks_sending"<<std::endl;
396 void RemoteClient::SetBlockNotSent(v3s16 p)
398 m_nearest_unsent_d = 0;
399 m_nothing_to_send_pause_timer = 0;
401 if(m_blocks_sending.find(p) != m_blocks_sending.end())
402 m_blocks_sending.erase(p);
403 if(m_blocks_sent.find(p) != m_blocks_sent.end())
404 m_blocks_sent.erase(p);
405 m_blocks_modified.insert(p);
408 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
410 m_nearest_unsent_d = 0;
411 m_nothing_to_send_pause_timer = 0;
413 for (auto &block : blocks) {
414 v3s16 p = block.first;
415 m_blocks_modified.insert(p);
417 if(m_blocks_sending.find(p) != m_blocks_sending.end())
418 m_blocks_sending.erase(p);
419 if(m_blocks_sent.find(p) != m_blocks_sent.end())
420 m_blocks_sent.erase(p);
424 void RemoteClient::notifyEvent(ClientStateEvent event)
426 std::ostringstream myerror;
430 //intentionally do nothing
435 m_state = CS_HelloSent;
438 m_state = CS_AwaitingInit2;
441 m_state = CS_Disconnecting;
446 /* GotInit2 SetDefinitionsSent SetMediaSent */
448 myerror << "Created: Invalid client state transition! " << event;
449 throw ClientStateError(myerror.str());
453 /* don't do anything if in denied state */
459 m_state = CS_AwaitingInit2;
460 if ((chosen_mech == AUTH_MECHANISM_SRP)
461 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
462 srp_verifier_delete((SRPVerifier *) auth_data);
463 chosen_mech = AUTH_MECHANISM_NONE;
466 m_state = CS_Disconnecting;
470 if ((chosen_mech == AUTH_MECHANISM_SRP)
471 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
472 srp_verifier_delete((SRPVerifier *) auth_data);
473 chosen_mech = AUTH_MECHANISM_NONE;
476 myerror << "HelloSent: Invalid client state transition! " << event;
477 throw ClientStateError(myerror.str());
480 case CS_AwaitingInit2:
484 confirmSerializationVersion();
485 m_state = CS_InitDone;
488 m_state = CS_Disconnecting;
494 /* Init SetDefinitionsSent SetMediaSent */
496 myerror << "InitSent: Invalid client state transition! " << event;
497 throw ClientStateError(myerror.str());
504 case CSE_SetDefinitionsSent:
505 m_state = CS_DefinitionsSent;
508 m_state = CS_Disconnecting;
514 /* Init GotInit2 SetMediaSent */
516 myerror << "InitDone: Invalid client state transition! " << event;
517 throw ClientStateError(myerror.str());
520 case CS_DefinitionsSent:
523 case CSE_SetClientReady:
527 m_state = CS_Disconnecting;
532 /* Init GotInit2 SetDefinitionsSent */
534 myerror << "DefinitionsSent: Invalid client state transition! " << event;
535 throw ClientStateError(myerror.str());
545 m_state = CS_Disconnecting;
547 case CSE_SudoSuccess:
548 m_state = CS_SudoMode;
549 if ((chosen_mech == AUTH_MECHANISM_SRP)
550 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
551 srp_verifier_delete((SRPVerifier *) auth_data);
552 chosen_mech = AUTH_MECHANISM_NONE;
554 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
556 myerror << "Active: Invalid client state transition! " << event;
557 throw ClientStateError(myerror.str());
568 m_state = CS_Disconnecting;
574 myerror << "Active: Invalid client state transition! " << event;
575 throw ClientStateError(myerror.str());
579 case CS_Disconnecting:
580 /* we are already disconnecting */
585 u64 RemoteClient::uptime() const
587 return porting::getTimeS() - m_connection_time;
590 ClientInterface::ClientInterface(con::Connection* con)
594 m_print_info_timer(0.0)
598 ClientInterface::~ClientInterface()
604 MutexAutoLock clientslock(m_clients_mutex);
606 for (auto &client_it : m_clients) {
608 delete client_it.second;
613 std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
615 std::vector<u16> reply;
616 MutexAutoLock clientslock(m_clients_mutex);
618 for (const auto &m_client : m_clients) {
619 if (m_client.second->getState() >= min_state)
620 reply.push_back(m_client.second->peer_id);
627 * Verify if user limit was reached.
628 * User limit count all clients from HelloSent state (MT protocol user) to Active state
629 * @return true if user limit was reached
631 bool ClientInterface::isUserLimitReached()
633 return getClientIDs(CS_HelloSent).size() >= g_settings->getU16("max_users");
636 void ClientInterface::step(float dtime)
638 m_print_info_timer += dtime;
639 if(m_print_info_timer >= 30.0)
641 m_print_info_timer = 0.0;
646 void ClientInterface::UpdatePlayerList()
649 std::vector<u16> clients = getClientIDs();
650 m_clients_names.clear();
654 infostream<<"Players:"<<std::endl;
656 for (u16 i : clients) {
657 RemotePlayer *player = m_env->getPlayer(i);
662 infostream << "* " << player->getName() << "\t";
665 MutexAutoLock clientslock(m_clients_mutex);
666 RemoteClient* client = lockedGetClientNoEx(i);
668 client->PrintInfo(infostream);
671 m_clients_names.emplace_back(player->getName());
676 void ClientInterface::send(u16 peer_id, u8 channelnum,
677 NetworkPacket* pkt, bool reliable)
679 m_con->Send(peer_id, channelnum, pkt, reliable);
682 void ClientInterface::sendToAll(NetworkPacket *pkt)
684 MutexAutoLock clientslock(m_clients_mutex);
685 for (auto &client_it : m_clients) {
686 RemoteClient *client = client_it.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 (auto &client_it : m_clients) {
701 RemoteClient *client = client_it.second;
702 NetworkPacket *pkt_to_send = nullptr;
704 if (client->net_proto_version >= min_proto_ver) {
706 } else if (client->net_proto_version != 0) {
707 pkt_to_send = legacypkt;
709 warningstream << "Client with unhandled version to handle: '"
710 << client->net_proto_version << "'";
714 m_con->Send(client->peer_id,
715 clientCommandFactoryTable[pkt_to_send->getCommand()].channel,
717 clientCommandFactoryTable[pkt_to_send->getCommand()].reliable);
721 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
723 MutexAutoLock clientslock(m_clients_mutex);
724 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
725 // The client may not exist; clients are immediately removed if their
726 // access is denied, and this event occurs later then.
727 if (n == m_clients.end())
730 if (n->second->getState() >= state_min)
736 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
738 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
739 // The client may not exist; clients are immediately removed if their
740 // access is denied, and this event occurs later then.
741 if (n == m_clients.end())
744 if (n->second->getState() >= state_min)
750 ClientState ClientInterface::getClientState(u16 peer_id)
752 MutexAutoLock clientslock(m_clients_mutex);
753 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
754 // The client may not exist; clients are immediately removed if their
755 // access is denied, and this event occurs later then.
756 if (n == m_clients.end())
759 return n->second->getState();
762 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
764 MutexAutoLock clientslock(m_clients_mutex);
765 RemoteClientMap::iterator n = m_clients.find(peer_id);
766 // The client may not exist; clients are immediately removed if their
767 // access is denied, and this event occurs later then.
768 if (n != m_clients.end())
769 n->second->setName(name);
772 void ClientInterface::DeleteClient(u16 peer_id)
774 MutexAutoLock conlock(m_clients_mutex);
777 RemoteClientMap::iterator n = m_clients.find(peer_id);
778 // The client may not exist; clients are immediately removed if their
779 // access is denied, and this event occurs later then.
780 if (n == m_clients.end())
784 Mark objects to be not known by the client
786 //TODO this should be done by client destructor!!!
787 RemoteClient *client = n->second;
789 for (u16 id : client->m_known_objects) {
791 ServerActiveObject* obj = m_env->getActiveObject(id);
793 if(obj && obj->m_known_by_count > 0)
794 obj->m_known_by_count--;
798 delete m_clients[peer_id];
799 m_clients.erase(peer_id);
802 void ClientInterface::CreateClient(u16 peer_id)
804 MutexAutoLock conlock(m_clients_mutex);
807 RemoteClientMap::iterator n = m_clients.find(peer_id);
808 // The client shouldn't already exist
809 if (n != m_clients.end()) return;
812 RemoteClient *client = new RemoteClient();
813 client->peer_id = peer_id;
814 m_clients[client->peer_id] = client;
817 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
820 MutexAutoLock clientlock(m_clients_mutex);
823 RemoteClientMap::iterator n = m_clients.find(peer_id);
825 // No client to deliver event
826 if (n == m_clients.end())
828 n->second->notifyEvent(event);
831 if ((event == CSE_SetClientReady) ||
832 (event == CSE_Disconnect) ||
833 (event == CSE_SetDenied))
839 u16 ClientInterface::getProtocolVersion(u16 peer_id)
841 MutexAutoLock conlock(m_clients_mutex);
844 RemoteClientMap::iterator n = m_clients.find(peer_id);
846 // No client to get version
847 if (n == m_clients.end())
850 return n->second->net_proto_version;
853 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
855 MutexAutoLock conlock(m_clients_mutex);
858 RemoteClientMap::iterator n = m_clients.find(peer_id);
860 // No client to set versions
861 if (n == m_clients.end())
864 n->second->setVersionInfo(major,minor,patch,full);