]> git.lizzy.rs Git - minetest.git/blobdiff - src/clientiface.cpp
Fix for #13255: Check if client has a block even if the server has unloaded it. ...
[minetest.git] / src / clientiface.cpp
index 28a0ee770ab52a49ace37e5a53671202f66c3c0c..9d1a6cd0383f56d80b89bc06bf74679f57bd82b8 100644 (file)
@@ -99,7 +99,6 @@ void RemoteClient::GetNextBlocks (
 {
        // Increment timers
        m_nothing_to_send_pause_timer -= dtime;
-       m_nearest_unsent_reset_timer += dtime;
 
        if (m_nothing_to_send_pause_timer >= 0)
                return;
@@ -139,34 +138,6 @@ void RemoteClient::GetNextBlocks (
        camera_dir.rotateYZBy(sao->getLookPitch());
        camera_dir.rotateXZBy(sao->getRotation().Y);
 
-       /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
-                       <<camera_dir.Z<<")"<<std::endl;*/
-
-       /*
-               Get the starting value of the block finder radius.
-       */
-
-       if (m_last_center != center) {
-               m_nearest_unsent_d = 0;
-               m_last_center = center;
-       }
-
-       /*infostream<<"m_nearest_unsent_reset_timer="
-                       <<m_nearest_unsent_reset_timer<<std::endl;*/
-
-       // Reset periodically to workaround for some bugs or stuff
-       if (m_nearest_unsent_reset_timer > 20.0f) {
-               m_nearest_unsent_reset_timer = 0.0f;
-               m_nearest_unsent_d = 0;
-               //infostream<<"Resetting m_nearest_unsent_d for "
-               //              <<server->getPlayerName(peer_id)<<std::endl;
-       }
-
-       //s16 last_nearest_unsent_d = m_nearest_unsent_d;
-       s16 d_start = m_nearest_unsent_d;
-
-       //infostream<<"d_start="<<d_start<<std::endl;
-
        u16 max_simul_sends_usually = m_max_simul_sends;
 
        /*
@@ -198,6 +169,29 @@ void RemoteClient::GetNextBlocks (
        s16 wanted_range = sao->getWantedRange() + 1;
        float camera_fov = sao->getFov();
 
+       /*
+               Get the starting value of the block finder radius.
+       */
+       if (m_last_center != center) {
+               m_nearest_unsent_d = 0;
+               m_last_center = center;
+       }
+       // reset the unsent distance if the view angle has changed more that 10% of the fov
+       // (this matches isBlockInSight which allows for an extra 10%)
+       if (camera_dir.dotProduct(m_last_camera_dir) < std::cos(camera_fov * 0.1f)) {
+               m_nearest_unsent_d = 0;
+               m_last_camera_dir = camera_dir;
+       }
+       if (m_nearest_unsent_d > 0) {
+               // make sure any blocks modified since the last time we sent blocks are resent
+               for (const v3s16 &p : m_blocks_modified) {
+                       m_nearest_unsent_d = std::min(m_nearest_unsent_d, center.getDistanceFrom(p));
+               }
+       }
+       m_blocks_modified.clear();
+
+       s16 d_start = m_nearest_unsent_d;
+
        // Distrust client-sent FOV and get server-set player object property
        // zoom FOV (degrees) as a check to avoid hacked clients using FOV to load
        // distant world.
@@ -212,13 +206,13 @@ void RemoteClient::GetNextBlocks (
                wanted_range);
        const s16 d_blocks_in_sight = full_d_max * BS * MAP_BLOCKSIZE;
 
-       s16 d_max = full_d_max;
        s16 d_max_gen = std::min(adjustDist(m_max_gen_distance, prop_zoom_fov),
                wanted_range);
 
-       // Don't loop very much at a time, adjust with distance,
-       // do more work per RTT with greater distances.
-       s16 max_d_increment_at_time = full_d_max / 9 + 1;
+       s16 d_max = full_d_max;
+
+       // Don't loop very much at a time
+       s16 max_d_increment_at_time = 2;
        if (d_max > d_start + max_d_increment_at_time)
                d_max = d_start + max_d_increment_at_time;
 
@@ -300,31 +294,26 @@ void RemoteClient::GetNextBlocks (
                                continue;
                        }
 
-                       /*
-                               Don't send already sent blocks
-                       */
-                       if (m_blocks_sent.find(p) != m_blocks_sent.end())
-                               continue;
-
                        /*
                                Check if map has this block
                        */
                        MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
-
-                       bool surely_not_found_on_disk = false;
-                       bool block_is_invalid = false;
                        if (block) {
-                               // Reset usage timer, this block will be of use in the future.
+                               // First: Reset usage timer, this block will be of use in the future.
                                block->resetUsageTimer();
+                       }
 
-                               // Block is dummy if data doesn't exist.
-                               // It means it has been not found from disk and not generated
-                               if (block->isDummy()) {
-                                       surely_not_found_on_disk = true;
-                               }
+                       /*
+                               Don't send already sent blocks
+                       */
+                       if (m_blocks_sent.find(p) != m_blocks_sent.end())
+                               continue;
 
+                       bool block_not_found = false;
+                       if (block) {
+                               // Check whether the block exists (with data)
                                if (!block->isGenerated())
-                                       block_is_invalid = true;
+                                       block_not_found = true;
 
                                /*
                                        If block is not close, don't send it unless it is near
@@ -338,7 +327,7 @@ void RemoteClient::GetNextBlocks (
                                                continue;
                                }
 
-                               if (m_occ_cull && !block_is_invalid &&
+                               if (m_occ_cull && !block_not_found &&
                                                env->getMap().isBlockOccluded(block, cam_pos_nodes)) {
                                        continue;
                                }
@@ -348,7 +337,7 @@ void RemoteClient::GetNextBlocks (
                                If block has been marked to not exist on disk (dummy) or is
                                not generated and generating new ones is not wanted, skip block.
                        */
-                       if (!generate && (surely_not_found_on_disk || block_is_invalid)) {
+                       if (!generate && block_not_found) {
                                // get next one.
                                continue;
                        }
@@ -356,7 +345,7 @@ void RemoteClient::GetNextBlocks (
                        /*
                                Add inexistent block to emerge queue.
                        */
-                       if (block == NULL || surely_not_found_on_disk || block_is_invalid) {
+                       if (block == NULL || block_not_found) {
                                if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
                                        if (nearest_emerged_d == -1)
                                                nearest_emerged_d = d;
@@ -409,21 +398,18 @@ void RemoteClient::GetNextBlocks (
 
 void RemoteClient::GotBlock(v3s16 p)
 {
-       if (m_blocks_modified.find(p) == m_blocks_modified.end()) {
-               if (m_blocks_sending.find(p) != m_blocks_sending.end())
-                       m_blocks_sending.erase(p);
-               else
-                       m_excess_gotblocks++;
-
+       if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
+               m_blocks_sending.erase(p);
+               // only add to sent blocks if it actually was sending
+               // (it might have been modified since)
                m_blocks_sent.insert(p);
+       } else {
+               m_excess_gotblocks++;
        }
 }
 
 void RemoteClient::SentBlock(v3s16 p)
 {
-       if (m_blocks_modified.find(p) != m_blocks_modified.end())
-               m_blocks_modified.erase(p);
-
        if (m_blocks_sending.find(p) == m_blocks_sending.end())
                m_blocks_sending[p] = 0.0f;
        else
@@ -433,29 +419,24 @@ void RemoteClient::SentBlock(v3s16 p)
 
 void RemoteClient::SetBlockNotSent(v3s16 p)
 {
-       m_nearest_unsent_d = 0;
        m_nothing_to_send_pause_timer = 0;
 
-       if (m_blocks_sending.find(p) != m_blocks_sending.end())
-               m_blocks_sending.erase(p);
-       if (m_blocks_sent.find(p) != m_blocks_sent.end())
-               m_blocks_sent.erase(p);
-       m_blocks_modified.insert(p);
+       // remove the block from sending and sent sets,
+       // and mark as modified if found
+       if (m_blocks_sending.erase(p) + m_blocks_sent.erase(p) > 0)
+               m_blocks_modified.insert(p);
 }
 
 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
 {
-       m_nearest_unsent_d = 0;
        m_nothing_to_send_pause_timer = 0;
 
        for (auto &block : blocks) {
                v3s16 p = block.first;
-               m_blocks_modified.insert(p);
-
-               if (m_blocks_sending.find(p) != m_blocks_sending.end())
-                       m_blocks_sending.erase(p);
-               if (m_blocks_sent.find(p) != m_blocks_sent.end())
-                       m_blocks_sent.erase(p);
+               // remove the block from sending and sent sets,
+               // and mark as modified if found
+               if (m_blocks_sending.erase(p) + m_blocks_sent.erase(p) > 0)
+                       m_blocks_modified.insert(p);
        }
 }
 
@@ -472,9 +453,6 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
                case CSE_Hello:
                        m_state = CS_HelloSent;
                        break;
-               case CSE_InitLegacy:
-                       m_state = CS_AwaitingInit2;
-                       break;
                case CSE_Disconnect:
                        m_state = CS_Disconnecting;
                        break;
@@ -495,20 +473,14 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
                {
                case CSE_AuthAccept:
                        m_state = CS_AwaitingInit2;
-                       if (chosen_mech == AUTH_MECHANISM_SRP ||
-                                       chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD)
-                               srp_verifier_delete((SRPVerifier *) auth_data);
-                       chosen_mech = AUTH_MECHANISM_NONE;
+                       resetChosenMech();
                        break;
                case CSE_Disconnect:
                        m_state = CS_Disconnecting;
                        break;
                case CSE_SetDenied:
                        m_state = CS_Denied;
-                       if (chosen_mech == AUTH_MECHANISM_SRP ||
-                                       chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD)
-                               srp_verifier_delete((SRPVerifier *) auth_data);
-                       chosen_mech = AUTH_MECHANISM_NONE;
+                       resetChosenMech();
                        break;
                default:
                        myerror << "HelloSent: Invalid client state transition! " << event;
@@ -584,9 +556,7 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
                        break;
                case CSE_SudoSuccess:
                        m_state = CS_SudoMode;
-                       if (chosen_mech == AUTH_MECHANISM_SRP)
-                               srp_verifier_delete((SRPVerifier *) auth_data);
-                       chosen_mech = AUTH_MECHANISM_NONE;
+                       resetChosenMech();
                        break;
                /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
                default:
@@ -619,6 +589,15 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
        }
 }
 
+void RemoteClient::resetChosenMech()
+{
+       if (auth_data) {
+               srp_verifier_delete((SRPVerifier *) auth_data);
+               auth_data = nullptr;
+       }
+       chosen_mech = AUTH_MECHANISM_NONE;
+}
+
 u64 RemoteClient::uptime() const
 {
        return porting::getTimeS() - m_connection_time;
@@ -694,7 +673,6 @@ void ClientInterface::UpdatePlayerList()
                std::vector<session_t> clients = getClientIDs();
                m_clients_names.clear();
 
-
                if (!clients.empty())
                        infostream<<"Players:"<<std::endl;
 
@@ -738,31 +716,6 @@ void ClientInterface::sendToAll(NetworkPacket *pkt)
        }
 }
 
-void ClientInterface::sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt,
-               u16 min_proto_ver)
-{
-       RecursiveMutexAutoLock clientslock(m_clients_mutex);
-       for (auto &client_it : m_clients) {
-               RemoteClient *client = client_it.second;
-               NetworkPacket *pkt_to_send = nullptr;
-
-               if (client->net_proto_version >= min_proto_ver) {
-                       pkt_to_send = pkt;
-               } else if (client->net_proto_version != 0) {
-                       pkt_to_send = legacypkt;
-               } else {
-                       warningstream << "Client with unhandled version to handle: '"
-                               << client->net_proto_version << "'";
-                       continue;
-               }
-
-               m_con->Send(client->peer_id,
-                       clientCommandFactoryTable[pkt_to_send->getCommand()].channel,
-                       pkt_to_send,
-                       clientCommandFactoryTable[pkt_to_send->getCommand()].reliable);
-       }
-}
-
 RemoteClient* ClientInterface::getClientNoEx(session_t peer_id, ClientState state_min)
 {
        RecursiveMutexAutoLock clientslock(m_clients_mutex);