From c8631d9a9b924c4c4d030bac3ed4e4a869ec2fd8 Mon Sep 17 00:00:00 2001 From: Howaner Date: Fri, 9 May 2014 23:10:02 +0200 Subject: [PATCH] Add DIG_STATUS_CANCELLED packet and add item resend, when a block can't place/break. --- src/ClientHandle.cpp | 61 ++++++++++++++++++++++++++++++++------------ src/ClientHandle.h | 3 +++ src/Inventory.cpp | 10 ++++++++ src/Inventory.h | 41 +++++++++++++++-------------- 4 files changed, 79 insertions(+), 36 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 94f031ed6..1535b0482 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -878,6 +878,7 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB case DIG_STATUS_CANCELLED: { // Block breaking cancelled by player + HandleBlockDigCancel(); return; } @@ -916,7 +917,7 @@ void cClientHandle::HandleBlockDigStarted(int a_BlockX, int a_BlockY, int a_Bloc // It is a duplicate packet, drop it right away return; } - + if ( m_Player->IsGameModeCreative() && ItemCategory::IsSword(m_Player->GetInventory().GetEquippedItem().m_ItemType) @@ -925,14 +926,7 @@ void cClientHandle::HandleBlockDigStarted(int a_BlockX, int a_BlockY, int a_Bloc // Players can't destroy blocks with a Sword in the hand. return; } - - if (cRoot::Get()->GetPluginManager()->CallHookPlayerBreakingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_OldBlock, a_OldMeta)) - { - // A plugin doesn't agree with the breaking. Bail out. Send the block back to the client, so that it knows: - m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); - 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_LastDigBlockX = a_BlockX; @@ -1004,16 +998,16 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo return; } - m_HasStartedDigging = false; - if (m_BlockDigAnimStage != -1) - { - // End dig animation - m_BlockDigAnimStage = -1; - // It seems that 10 ends block animation - m_Player->GetWorld()->BroadcastBlockBreakAnimation(m_UniqueID, m_BlockDigAnimX, m_BlockDigAnimY, m_BlockDigAnimZ, 10, this); - } + HandleBlockDigCancel(); cItemHandler * ItemHandler = cItemHandler::GetItemHandler(m_Player->GetEquippedItem()); + + if (cRoot::Get()->GetPluginManager()->CallHookPlayerBreakingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_OldBlock, a_OldMeta)) + { + // A plugin doesn't agree with the breaking. Bail out. Send the block back to the client, so that it knows: + m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); + return; + } if (a_OldBlock == E_BLOCK_AIR) { @@ -1036,6 +1030,36 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo +void cClientHandle::HandleBlockDigCancel() +{ + if ( + !m_HasStartedDigging || // Hasn't received the DIG_STARTED packet + (m_LastDigBlockX == -1) || + (m_LastDigBlockY == -1) || + (m_LastDigBlockZ == -1) + ) + { + return; + } + + m_HasStartedDigging = false; + if (m_BlockDigAnimStage != -1) + { + // End dig animation + m_BlockDigAnimStage = -1; + // It seems that 10 ends block animation + m_Player->GetWorld()->BroadcastBlockBreakAnimation(m_UniqueID, m_LastDigBlockX, m_LastDigBlockY, m_LastDigBlockZ, 10, this); + } + + m_BlockDigAnimX = -1; + m_BlockDigAnimY = -1; + m_BlockDigAnimZ = -1; +} + + + + + void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, const cItem & a_HeldItem) { LOGD("HandleRightClick: {%d, %d, %d}, face %d, HeldItem: %s", @@ -1058,6 +1082,7 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); //2 block high things + m_Player->GetInventory().SendEquippedSlot(); } return; } @@ -1246,6 +1271,7 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, e { // Handler refused the placement, send that information back to the client: World->SendBlockTo(a_BlockX, a_BlockY, a_BlockY, m_Player); + m_Player->GetInventory().SendEquippedSlot(); return; } @@ -1255,6 +1281,7 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, e { // A plugin doesn't agree with placing the block, revert the block on the client: World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); + m_Player->GetInventory().SendEquippedSlot(); return; } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 4dc6ab074..03a716657 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -374,6 +374,9 @@ private: /** Handles the DIG_FINISHED dig packet: */ void HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta); + /** Handles the DIG_CANCELLED dig packet: */ + void HandleBlockDigCancel(); + /** Converts the protocol-formatted channel list (NUL-separated) into a proper string vector. */ AStringVector BreakApartPluginChannels(const AString & a_PluginChannels); diff --git a/src/Inventory.cpp b/src/Inventory.cpp index a365e4ed4..bce882c88 100644 --- a/src/Inventory.cpp +++ b/src/Inventory.cpp @@ -243,6 +243,16 @@ void cInventory::SetHotbarSlot(int a_HotBarSlotNum, const cItem & a_Item) +void cInventory::SendEquippedSlot() +{ + int EquippedSlotNum = cInventory::invArmorCount + cInventory::invInventoryCount + GetEquippedSlotNum(); + SendSlot(EquippedSlotNum); +} + + + + + const cItem & cInventory::GetSlot(int a_SlotNum) const { if ((a_SlotNum < 0) || (a_SlotNum >= invNumSlots)) diff --git a/src/Inventory.h b/src/Inventory.h index 1ad7c4776..39aef1538 100644 --- a/src/Inventory.h +++ b/src/Inventory.h @@ -56,13 +56,13 @@ public: // tolua_begin - /// Removes all items from the entire inventory + /** Removes all items from the entire inventory */ void Clear(void); - /// Returns number of items out of a_ItemStack that can fit in the storage + /** Returns number of items out of a_ItemStack that can fit in the storage */ int HowManyCanFit(const cItem & a_ItemStack, bool a_ConsiderEmptySlots); - /// Returns how many items of the specified type would fit into the slot range specified + /** Returns how many items of the specified type would fit into the slot range specified */ int HowManyCanFit(const cItem & a_ItemStack, int a_BeginSlotNum, int a_EndSlotNum, bool a_ConsiderEmptySlots); /** Adds as many items out of a_ItemStack as can fit. @@ -86,33 +86,36 @@ public: */ int AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks, bool a_tryToFillEquippedFirst); - /// Removes one item out of the currently equipped item stack, returns true if successful, false if empty-handed + /** Removes one item out of the currently equipped item stack, returns true if successful, false if empty-handed */ bool RemoveOneEquippedItem(void); - /// Returns the number of items of type a_Item that are stored + /** Returns the number of items of type a_Item that are stored */ int HowManyItems(const cItem & a_Item); - /// Returns true if there are at least as many items of type a_ItemStack as in a_ItemStack + /** Returns true if there are at least as many items of type a_ItemStack as in a_ItemStack */ bool HasItems(const cItem & a_ItemStack); + + /** Sends the equipped item slot to the client */ + void SendEquippedSlot(); - /// Returns the cItemGrid object representing the armor slots + /** Returns the cItemGrid object representing the armor slots */ cItemGrid & GetArmorGrid(void) { return m_ArmorSlots; } - /// Returns the cItemGrid object representing the main inventory slots + /** Returns the cItemGrid object representing the main inventory slots */ cItemGrid & GetInventoryGrid(void) { return m_InventorySlots; } - /// Returns the cItemGrid object representing the hotbar slots + /** Returns the cItemGrid object representing the hotbar slots */ cItemGrid & GetHotbarGrid(void) { return m_HotbarSlots; } - /// Returns the player associated with this inventory + /** Returns the player associated with this inventory */ cPlayer & GetOwner(void) { return m_Owner; } - /// Copies the non-empty slots into a_ItemStacks; preserves the original a_Items contents + /** Copies the non-empty slots into a_ItemStacks; preserves the original a_Items contents */ void CopyToItems(cItems & a_Items); // tolua_end - /// Returns the player associated with this inventory (const version) + /** Returns the player associated with this inventory (const version) */ const cPlayer & GetOwner(void) const { return m_Owner; } // tolua_begin @@ -136,10 +139,10 @@ public: */ int ChangeSlotCount(int a_SlotNum, int a_AddToCount); - /// Adds the specified damage to the specified item; deletes the item and returns true if the item broke. + /** Adds the specified damage to the specified item; deletes the item and returns true if the item broke. */ bool DamageItem(int a_SlotNum, short a_Amount); - /// Adds the specified damage to the currently held item; deletes the item and returns true if the item broke. + /** Adds the specified damage to the currently held item; deletes the item and returns true if the item broke. */ bool DamageEquippedItem(short a_Amount = 1); const cItem & GetEquippedHelmet (void) const { return m_ArmorSlots.GetSlot(0); } @@ -149,13 +152,13 @@ public: // tolua_end - /// Sends the slot contents to the owner + /** Sends the slot contents to the owner */ void SendSlot(int a_SlotNum); - /// Update items (e.g. Maps) + /** Update items (e.g. Maps) */ void UpdateItems(void); - /// Converts an armor slot number into the ID for the EntityEquipment packet + /** Converts an armor slot number into the ID for the EntityEquipment packet */ static int ArmorSlotNumToEntityEquipmentID(short a_ArmorSlotNum); void SaveToJson(Json::Value & a_Value); @@ -172,10 +175,10 @@ protected: cPlayer & m_Owner; - /// Returns the ItemGrid and the (grid-local) slot number for a (global) slot number; return NULL for invalid SlotNum + /** Returns the ItemGrid and the (grid-local) slot number for a (global) slot number; return NULL for invalid SlotNum */ const cItemGrid * GetGridForSlotNum(int a_SlotNum, int & a_GridSlotNum) const; - /// Returns the ItemGrid and the (grid-local) slot number for a (global) slot number; return NULL for invalid SlotNum + /** Returns the ItemGrid and the (grid-local) slot number for a (global) slot number; return NULL for invalid SlotNum */ cItemGrid * GetGridForSlotNum(int a_SlotNum, int & a_GridSlotNum); // cItemGrid::cListener override: