From d49ce751ba6f8f2eb171633cea30a1119935f8c7 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 11 Nov 2021 21:02:29 +0000 Subject: Miscellaneous fixes (#5320) * Protocol: update Abilities flags + Add Spectator handling * BioGen: move include * ClientHandle: rename Respawn packet dimension check flag * Make it clearer what it's doing. * ClientHandle: move ProcessProtocolIn calls to World * Player: remove some redundant initialisation * Player: UpdateCapabilities enables flight for spectators * Produce growth: improve comments * ClientHandle: run unload checks using delta time * Fix forgotten initialisation of time member --- src/ClientHandle.cpp | 108 +++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 55 deletions(-) (limited to 'src/ClientHandle.cpp') diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 4745ff7cd..a42212002 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -76,6 +76,7 @@ cClientHandle::cClientHandle(const AString & a_IPString, int a_ViewDistance) : m_LastStreamedChunkX(std::numeric_limits::max()), // bogus chunk coords to force streaming upon login m_LastStreamedChunkZ(std::numeric_limits::max()), m_TicksSinceLastPacket(0), + m_TimeSinceLastUnloadCheck(0), m_Ping(1000), m_PingID(1), m_BlockDigAnimStage(-1), @@ -243,6 +244,36 @@ void cClientHandle::ProxyInit(const AString & a_IPString, const cUUID & a_UUID, +void cClientHandle::ProcessProtocolIn(void) +{ + // Process received network data: + decltype(m_IncomingData) IncomingData; + { + cCSLock Lock(m_CSIncomingData); + + // Bail out when nothing was received: + if (m_IncomingData.empty()) + { + return; + } + + std::swap(IncomingData, m_IncomingData); + } + + try + { + m_Protocol.HandleIncomingData(*this, IncomingData); + } + catch (const std::exception & Oops) + { + Kick(Oops.what()); + } +} + + + + + void cClientHandle::ProcessProtocolOut() { decltype(m_OutgoingData) OutgoingData; @@ -394,7 +425,7 @@ void cClientHandle::FinishAuthenticate() } catch (const std::exception & Oops) { - LOGWARNING("Error reading player \"%s\": %s", GetUsername().c_str(), Oops.what()); + LOGWARNING("Player \"%s\" save or statistics file loading failed: %s", GetUsername().c_str(), Oops.what()); Kick("Contact an operator.\n\nYour player's save files could not be parsed.\nTo avoid data loss you are prevented from joining."); return; } @@ -632,8 +663,6 @@ void cClientHandle::UnloadOutOfRangeChunks(void) m_Player->GetWorld()->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkZ, this); SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ); } - - m_LastUnloadCheck = m_Player->GetWorld()->GetWorldAge(); } @@ -815,8 +844,8 @@ void cClientHandle::HandleEnchantItem(UInt8 a_WindowID, UInt8 a_Enchantment) // Only allow enchantment if the player has sufficient levels and lapis to enchant: if ((m_Player->GetCurrentXp() >= XpRequired) && (LapisStack.m_ItemCount >= LapisRequired)) { - /** We need to reduce the player's level by the number of lapis required. - However we need to keep the resulting percentage filled the same. */ + // We need to reduce the player's level by the number of lapis required. + // However we need to keep the resulting percentage filled the same. const auto TargetLevel = m_Player->GetXpLevel() - LapisRequired; const auto CurrentFillPercent = m_Player->GetXpPercentage(); @@ -842,7 +871,7 @@ void cClientHandle::HandleEnchantItem(UInt8 a_WindowID, UInt8 a_Enchantment) } } - // Retrieve the enchanted item corresponding to our chosen option (top, middle, bottom) + // The enchanted item corresponding to our chosen option (top, middle, bottom). cItem EnchantedItem = Window->m_SlotArea->SelectEnchantedOption(a_Enchantment); // Set the item slot to our new enchanted item: @@ -2071,19 +2100,10 @@ bool cClientHandle::CheckBlockInteractionsRate(void) -void cClientHandle::Tick(float a_Dt) +void cClientHandle::Tick(std::chrono::milliseconds a_Dt) { using namespace std::chrono_literals; - // anticheat fastbreak - if (m_HasStartedDigging) - { - BLOCKTYPE Block = m_Player->GetWorld()->GetBlock({ m_LastDigBlockX, m_LastDigBlockY, m_LastDigBlockZ }); - m_BreakProgress += m_Player->GetMiningProgressPerTick(Block); - } - - ProcessProtocolIn(); - if (IsDestroyed()) { return; @@ -2156,16 +2176,24 @@ void cClientHandle::Tick(float a_Dt) StreamNextChunks(); // Unload all chunks that are out of the view distance (every 5 seconds): - if ((m_Player->GetWorld()->GetWorldAge() - m_LastUnloadCheck) > 5s) + if ((m_TimeSinceLastUnloadCheck += a_Dt) > 5s) { UnloadOutOfRangeChunks(); + m_TimeSinceLastUnloadCheck = 0s; + } + + // anticheat fastbreak + if (m_HasStartedDigging) + { + BLOCKTYPE Block = m_Player->GetWorld()->GetBlock({ m_LastDigBlockX, m_LastDigBlockY, m_LastDigBlockZ }); + m_BreakProgress += m_Player->GetMiningProgressPerTick(Block); } // Handle block break animation: if (m_BlockDigAnimStage > -1) { int lastAnimVal = m_BlockDigAnimStage; - m_BlockDigAnimStage += static_cast(m_BlockDigAnimSpeed * a_Dt); + m_BlockDigAnimStage += static_cast(m_BlockDigAnimSpeed * a_Dt.count()); if (m_BlockDigAnimStage > 9000) { m_BlockDigAnimStage = 9000; @@ -2903,17 +2931,17 @@ void cClientHandle::SendResetTitle() -void cClientHandle::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) +void cClientHandle::SendRespawn(const eDimension a_Dimension, const bool a_IsRespawningFromDeath) { - if (!a_ShouldIgnoreDimensionChecks && (a_Dimension == m_Player->GetWorld()->GetDimension())) + if (!a_IsRespawningFromDeath && (a_Dimension == m_Player->GetWorld()->GetDimension())) { // The client goes crazy if we send a respawn packet with the dimension of the current world // So we send a temporary one first. - // This is not needed when the player dies, hence the a_ShouldIgnoreDimensionChecks flag. - // a_ShouldIgnoreDimensionChecks is true only at cPlayer::Respawn, which is called after - // the player dies. - eDimension TemporaryDimension = (a_Dimension == dimOverworld) ? dimNether : dimOverworld; - m_Protocol->SendRespawn(TemporaryDimension); + // This is not needed when the player dies, hence the a_IsRespawningFromDeath flag. + // a_IsRespawningFromDeath is true only at cPlayer::Respawn, which is called after the player dies. + + // First send a temporary dimension to placate the client: + m_Protocol->SendRespawn((a_Dimension == dimOverworld) ? dimNether : dimOverworld); } m_Protocol->SendRespawn(a_Dimension); @@ -3383,36 +3411,6 @@ bool cClientHandle::SetState(eState a_NewState) -void cClientHandle::ProcessProtocolIn(void) -{ - // Process received network data: - decltype(m_IncomingData) IncomingData; - { - cCSLock Lock(m_CSIncomingData); - - // Bail out when nothing was received: - if (m_IncomingData.empty()) - { - return; - } - - std::swap(IncomingData, m_IncomingData); - } - - try - { - m_Protocol.HandleIncomingData(*this, IncomingData); - } - catch (const std::exception & Oops) - { - Kick(Oops.what()); - } -} - - - - - void cClientHandle::OnLinkCreated(cTCPLinkPtr a_Link) { m_Link = a_Link; -- cgit v1.2.3