From 64a24a4c79ace77ff111f0b555ff1d9d942bf56e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 16 Jul 2022 12:04:14 +0100 Subject: ClientHandle: Fix block interaction regressions (#5431) * ClientHandle: Fix block interaction regressions * Fix reach distance being halved. * Fix fire extinguish not working, fixes #5422. * AddFaceDirection: deprecate non-vector version --- Server/Plugins/APIDump/APIDesc.lua | 9 +++--- src/Blocks/BlockRail.h | 4 ++- src/ClientHandle.cpp | 56 +++++++++++++++-------------------- src/ClientHandle.h | 3 ++ src/Defines.cpp | 60 +++++++++++++++++--------------------- src/Defines.h | 8 ++--- 6 files changed, 61 insertions(+), 79 deletions(-) diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index 227e4a6fa..03fb31990 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -14299,13 +14299,13 @@ end Type = "number", }, }, - Notes = "Returns the coords of a block adjacent to the specified block through the specified {{Globals#BlockFaces|face}}", + Notes = "OBSOLETE, use the vector version instead.", }, { Params = { { - Name = "BlockPos", + Name = "Position", Type = "Vector3i", }, { @@ -14313,7 +14313,7 @@ end Type = "eBlockFace", }, { - Name = "IsInverse", + Name = "InvertDirection", Type = "boolean", IsOptional = true, }, @@ -14321,11 +14321,10 @@ end Returns = { { - Name = "BlockPos", Type = "Vector3i", }, }, - Notes = "Returns the coords of a block adjacent to the specified block through the specified {{Globals#BlockFaces|face}}", + Notes = "By default, returns the coordinates adjacent to the specified block through the specified face. If inverted, returns the coordinates adjacent to the opposite face.", }, }, Base64Decode = diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h index d822e728f..6c4367334 100644 --- a/src/Blocks/BlockRail.h +++ b/src/Blocks/BlockRail.h @@ -326,8 +326,10 @@ private: static bool IsNotConnected(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, eBlockFace a_BlockFace, char a_Pure = 0) { - AddFaceDirection(a_Pos.x, a_Pos.y, a_Pos.z, a_BlockFace, false); + a_Pos = AddFaceDirection(a_Pos, a_BlockFace, false); + NIBBLETYPE Meta; + if (!IsBlockRail(a_ChunkInterface.GetBlock(a_Pos))) { if (!IsBlockRail(a_ChunkInterface.GetBlock(a_Pos + Vector3i(0, 1, 0))) || (a_Pure != E_PURE_UPDOWN)) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index ef596baf0..5a2e1d620 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1117,17 +1117,15 @@ void cClientHandle::HandleLeftClick(Vector3i a_BlockPos, eBlockFace a_BlockFace, /* Check for clickthrough-blocks: When the user breaks a fire block, the client send the wrong block location. We must find the right block with the face direction. */ - - Vector3i BlockPos = a_BlockPos; - AddFaceDirection(BlockPos, a_BlockFace); - - if (cChunkDef::IsValidHeight(BlockPos) && cBlockInfo::IsClickedThrough(m_Player->GetWorld()->GetBlock(BlockPos))) + if ( + const auto InterferingPosition = AddFaceDirection(a_BlockPos, a_BlockFace); + cChunkDef::IsValidHeight(InterferingPosition) && cBlockInfo::IsClickedThrough(m_Player->GetWorld()->GetBlock(InterferingPosition)) + ) { - a_BlockPos = BlockPos; + a_BlockPos = InterferingPosition; } - constexpr double MaxBlockDistance = 6.0; - if (!cBoundingBox(m_Player->GetPosition(), MaxBlockDistance).IsInside(a_BlockPos)) + if (!IsWithinReach(a_BlockPos)) { m_Player->SendBlocksAround(a_BlockPos, 2); return; @@ -1270,13 +1268,6 @@ void cClientHandle::HandleBlockDigStarted(Vector3i a_BlockPos, eBlockFace a_Bloc return; } - constexpr double MaxBlockDistance = 6.0; - if (!cBoundingBox(m_Player->GetPosition(), MaxBlockDistance).IsInside(a_BlockPos)) - { - m_Player->SendBlocksAround(a_BlockPos, 2); - return; - } - // Set the last digging coords to the block being dug, so that they can be checked in DIG_FINISHED to avoid dig / aim bug in the client: m_HasStartedDigging = true; m_LastDigBlockPos = a_BlockPos; @@ -1439,27 +1430,13 @@ void cClientHandle::HandleRightClick(Vector3i a_BlockPos, eBlockFace a_BlockFace // TODO: We are still consuming the items in main hand. Remove this override when the off-hand consumption is handled correctly. a_UsedMainHand = true; - const cItem & HeldItem = a_UsedMainHand ? m_Player->GetEquippedItem() : m_Player->GetInventory().GetShieldSlot(); - - // Distance from the block's center to the player's eye height. - const double Dist = (Vector3d(0.5, 0.5, 0.5) + a_BlockPos - m_Player->GetEyePosition()).SqrLength(); - - // Check the reach distance: - // _X 2014-11-25: I've maxed at 5.26 with a Survival client and 5.78 with a Creative client in my tests - double MaxDist = m_Player->IsGameModeCreative() ? 33.4084 : 27.6676; - bool IsWithinReach = (Dist <= MaxDist); - - FLOGD("HandleRightClick: {0}, face {1}, Cursor {2}, Hand: {3}, HeldItem: {4}; Dist: {5:.02f}", - a_BlockPos, a_BlockFace, a_CursorPos, a_UsedMainHand, ItemToFullString(HeldItem), Dist - ); - cWorld * World = m_Player->GetWorld(); cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); + const cItem & HeldItem = a_UsedMainHand ? m_Player->GetEquippedItem() : m_Player->GetInventory().GetShieldSlot(); - if ( - !PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos) && - IsWithinReach && !m_Player->IsFrozen() - ) + FLOGD("HandleRightClick: {0}, face {1}, Cursor {2}, Hand: {3}, HeldItem: {4}", a_BlockPos, a_BlockFace, a_CursorPos, a_UsedMainHand, ItemToFullString(HeldItem)); + + if (!PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos) && IsWithinReach(a_BlockPos) && !m_Player->IsFrozen()) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; @@ -2101,6 +2078,19 @@ bool cClientHandle::CheckBlockInteractionsRate(void) +bool cClientHandle::IsWithinReach(const Vector3i a_Position) const +{ + // Distance from the block's center to the player's eye height. + const double Distance = (Vector3d(0.5, 0.5, 0.5) + a_Position - m_Player->GetEyePosition()).SqrLength(); + + // _X 2014-11-25: I've maxed at 5.26 with a Survival client and 5.78 with a Creative client in my tests. + return Distance <= (m_Player->IsGameModeCreative() ? 33.4084 : 27.6676); +} + + + + + void cClientHandle::Tick(std::chrono::milliseconds a_Dt) { using namespace std::chrono_literals; diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 9f3cbb18d..c5949b57b 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -581,6 +581,9 @@ private: /** Returns true if the rate block interactions is within a reasonable limit (bot protection) */ bool CheckBlockInteractionsRate(void); + /** Returns whether the player could in fact reach the position they're attempting to interact with. */ + bool IsWithinReach(Vector3i a_Position) const; + /** Adds a single chunk to be streamed to the client; used by StreamChunks() */ void StreamChunk(int a_ChunkX, int a_ChunkZ, cChunkSender::Priority a_Priority); diff --git a/src/Defines.cpp b/src/Defines.cpp index aa5e46995..e00e9f7e6 100644 --- a/src/Defines.cpp +++ b/src/Defines.cpp @@ -377,42 +377,34 @@ eDamageType StringToDamageType(const AString & a_DamageTypeString) void AddFaceDirection(int & a_BlockX, int & a_BlockY, int & a_BlockZ, eBlockFace a_BlockFace, bool a_bInverse) { - if (!a_bInverse) - { - switch (a_BlockFace) - { - case BLOCK_FACE_YP: a_BlockY++; break; - case BLOCK_FACE_YM: a_BlockY--; break; - case BLOCK_FACE_ZM: a_BlockZ--; break; - case BLOCK_FACE_ZP: a_BlockZ++; break; - case BLOCK_FACE_XP: a_BlockX++; break; - case BLOCK_FACE_XM: a_BlockX--; break; - case BLOCK_FACE_NONE: - { - LOGWARNING("%s: Unknown face: %d", __FUNCTION__, a_BlockFace); - ASSERT(!"AddFaceDirection(): Unknown face"); - break; - } - } - } - else + LOGWARNING("AddFaceDirection with X/Y/Z parameters is deprecated, use the vector version"); + + const auto Offset = AddFaceDirection({ a_BlockX, a_BlockY, a_BlockZ }, a_BlockFace, a_bInverse); + a_BlockX = Offset.x; + a_BlockY = Offset.y; + a_BlockZ = Offset.z; +} + + + + + +Vector3i AddFaceDirection(const Vector3i a_Position, const eBlockFace a_BlockFace, const bool a_InvertDirection) +{ + const int Offset = a_InvertDirection ? -1 : 1; + + switch (a_BlockFace) { - switch (a_BlockFace) - { - case BLOCK_FACE_YP: a_BlockY--; break; - case BLOCK_FACE_YM: a_BlockY++; break; - case BLOCK_FACE_ZM: a_BlockZ++; break; - case BLOCK_FACE_ZP: a_BlockZ--; break; - case BLOCK_FACE_XP: a_BlockX--; break; - case BLOCK_FACE_XM: a_BlockX++; break; - case BLOCK_FACE_NONE: - { - LOGWARNING("%s: Unknown inv face: %d", __FUNCTION__, a_BlockFace); - ASSERT(!"AddFaceDirection(): Unknown face"); - break; - } - } + case BLOCK_FACE_YP: return a_Position.addedY(+Offset); + case BLOCK_FACE_YM: return a_Position.addedY(-Offset); + case BLOCK_FACE_ZM: return a_Position.addedZ(-Offset); + case BLOCK_FACE_ZP: return a_Position.addedZ(+Offset); + case BLOCK_FACE_XP: return a_Position.addedX(+Offset); + case BLOCK_FACE_XM: return a_Position.addedX(-Offset); + case BLOCK_FACE_NONE: break; } + + UNREACHABLE("Unsupported block face"); } diff --git a/src/Defines.h b/src/Defines.h index 82b85e3c4..bbe5d3d3d 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -570,12 +570,8 @@ If a_Inverse is true, the opposite direction is used instead. */ void AddFaceDirection(int & a_BlockX, int & a_BlockY, int & a_BlockZ, eBlockFace a_BlockFace, bool a_bInverse = false); /** Returns the coords of a block that is neighboring the specified position through its specified face. -If a_IsInverse is true, the opposite direction is used instead. */ -inline Vector3i AddFaceDirection(Vector3i a_Pos, eBlockFace a_BlockFace, bool a_bInverse = false) -{ - AddFaceDirection(a_Pos.x, a_Pos.y, a_Pos.z, a_BlockFace, a_bInverse); - return a_Pos; -} +If a_InvertDirection is true, the opposite direction is used instead. */ +Vector3i AddFaceDirection(Vector3i a_Pos, eBlockFace a_BlockFace, bool a_InvertDirection = false); // tolua_end -- cgit v1.2.3