diff --git a/src/source/NewUIInventoryCtrl.cpp b/src/source/NewUIInventoryCtrl.cpp index 12db67aeb..8bad92889 100644 --- a/src/source/NewUIInventoryCtrl.cpp +++ b/src/source/NewUIInventoryCtrl.cpp @@ -534,6 +534,80 @@ void SEASON3B::CNewUIInventoryCtrl::RemoveItem(ITEM* pItem) } } +bool SEASON3B::CNewUIInventoryCtrl::RemoveItemAt(int iLinealPos) +{ + iLinealPos -= m_nIndexOffset; + ITEM* pItem = this->FindItemFromSlotIndex(iLinealPos, true); + if (pItem == nullptr) + { + return false; + } + + this->RemoveItem(pItem); + return true; +} + +ITEM* SEASON3B::CNewUIInventoryCtrl::FindItemFromSlotIndex(const int slotIndex, const bool recoverIfMissing) +{ + if (slotIndex < 0 || slotIndex >= m_nColumn * m_nRow) + { + return nullptr; + } + + const DWORD key = m_pdwItemCheckBox[slotIndex]; + if (key <= 1) + { + return nullptr; + } + + ITEM* pItem = this->FindItemByKey(key); + if (pItem != nullptr) + { + return pItem; + } + + if (recoverIfMissing) + { + this->ClearSlotKey(key); + this->RequestInventoryRefresh(); + } + + return nullptr; +} + +void SEASON3B::CNewUIInventoryCtrl::ClearSlotKey(const DWORD key) +{ + if (key == 0) + { + return; + } + + for (int i = 0; i < m_nColumn * m_nRow; ++i) + { + if (m_pdwItemCheckBox[i] == key) + { + m_pdwItemCheckBox[i] = 0; + } + } +} + +void SEASON3B::CNewUIInventoryCtrl::RequestInventoryRefresh() const +{ + static DWORD lastRefreshRequestTick = 0; + const DWORD currentTick = GetTickCount(); + if (currentTick - lastRefreshRequestTick < 1000) + { + return; + } + + lastRefreshRequestTick = currentTick; + + if (SocketClient != nullptr && SocketClient->ToGameServer() != nullptr) + { + SocketClient->ToGameServer()->SendInventoryRequest(); + } +} + void SEASON3B::CNewUIInventoryCtrl::RemoveAllItems() { memset(m_pdwItemCheckBox, 0, sizeof(DWORD) * m_nColumn * m_nRow); @@ -583,12 +657,7 @@ void SEASON3B::CNewUIInventoryCtrl::GetSquareColorWarning(float* pfParams) const ITEM* SEASON3B::CNewUIInventoryCtrl::FindItem(int iLinealPos) { iLinealPos -= m_nIndexOffset; - if (iLinealPos >= 0 && iLinealPos < m_nColumn * m_nRow) - { - const DWORD dwKey = m_pdwItemCheckBox[iLinealPos]; - return FindItemByKey(dwKey); - } - return nullptr; + return this->FindItemFromSlotIndex(iLinealPos, true); } ITEM* SEASON3B::CNewUIInventoryCtrl::FindItem(int iColumnX, int iRowY) @@ -819,7 +888,7 @@ bool SEASON3B::CNewUIInventoryCtrl::UpdateMouseEvent() ) { m_EventState = EVENT_PICKING; - ITEM* pItem = FindItemByKey(m_pdwItemCheckBox[m_iPointedSquareIndex - m_nIndexOffset]); + ITEM* pItem = this->FindItem(m_iPointedSquareIndex); if (pItem) { if (CreatePickedItem(this, pItem)) @@ -835,8 +904,8 @@ bool SEASON3B::CNewUIInventoryCtrl::UpdateMouseEvent() && nullptr == GetPickedItem() && (m_pdwItemCheckBox[m_iPointedSquareIndex - m_nIndexOffset] > 1) && g_pNewUIMng) { - ITEM* pItem = FindItemByKey(m_pdwItemCheckBox[m_iPointedSquareIndex - m_nIndexOffset]); - if (pItem != m_pToolTipItem) + ITEM* pItem = this->FindItem(m_iPointedSquareIndex); + if (pItem != nullptr && pItem != m_pToolTipItem) { CreateItemToolTip(pItem); @@ -871,8 +940,13 @@ void SEASON3B::CNewUIInventoryCtrl::UpdateProcess() m_iPointedSquareIndex = iCurSquareIndex; } - if (m_iPointedSquareIndex == -1 - || (m_iPointedSquareIndex != -1 && m_pdwItemCheckBox[m_iPointedSquareIndex - m_nIndexOffset] == 0)) + bool hasValidPointedItem = false; + if (m_iPointedSquareIndex != -1) + { + hasValidPointedItem = this->FindItem(m_iPointedSquareIndex) != nullptr; + } + + if (m_iPointedSquareIndex == -1 || !hasValidPointedItem) { m_EventState = EVENT_NONE; DeleteItemToolTip(); @@ -888,11 +962,12 @@ void SEASON3B::CNewUIInventoryCtrl::Render() { const int iCurSquareIndex = y * m_nColumn + x; - if (m_pdwItemCheckBox[iCurSquareIndex] > 1) + const DWORD slotKey = m_pdwItemCheckBox[iCurSquareIndex]; + if (slotKey > 1) { EnableAlphaTest(); - ITEM* pItem = FindItemByKey(m_pdwItemCheckBox[iCurSquareIndex]); + ITEM* pItem = FindItemByKey(slotKey); if (pItem) { @@ -928,7 +1003,9 @@ void SEASON3B::CNewUIInventoryCtrl::Render() } else { - glColor4f(0.3f, 0.5f, 0.5f, 0.6f); + this->ClearSlotKey(slotKey); + this->RequestInventoryRefresh(); + glColor4f(0.f, 0.f, 0.f, 0.f); } RenderColor(m_Pos.x + (x * INVENTORY_SQUARE_WIDTH), m_Pos.y + (y * INVENTORY_SQUARE_HEIGHT), INVENTORY_SQUARE_WIDTH, INVENTORY_SQUARE_HEIGHT); @@ -1247,9 +1324,16 @@ bool SEASON3B::CNewUIInventoryCtrl::CheckSlot(int startIndex, int width, int hei return false; } - if (m_pdwItemCheckBox[iIndex] != 0) + const DWORD slotKey = m_pdwItemCheckBox[iIndex]; + if (slotKey != 0) { - return false; + if (slotKey == 1 || this->FindItemByKey(slotKey) != nullptr) + { + return false; + } + + this->ClearSlotKey(slotKey); + this->RequestInventoryRefresh(); } } } @@ -1507,9 +1591,14 @@ void SEASON3B::CNewUIInventoryCtrl::BackupPickedItem() ITEM* pItemObj = ms_pPickedItem->GetItem(); if (pOwner) { - pOwner->AddItem(pItemObj->x, pItemObj->y, pItemObj); - - DeletePickedItem(); + if (pOwner->AddItem(pItemObj->x, pItemObj->y, pItemObj)) + { + DeletePickedItem(); + } + else + { + pOwner->RequestInventoryRefresh(); + } } else if (pItemObj->ex_src_type == ITEM_EX_SRC_EQUIPMENT) { @@ -1734,4 +1823,4 @@ bool SEASON3B::CNewUIInventoryCtrl::CanUpgradeItem(ITEM* pSourceItem, ITEM* pTar } return false; -} \ No newline at end of file +} diff --git a/src/source/NewUIInventoryCtrl.h b/src/source/NewUIInventoryCtrl.h index 1298ad49c..14af5a61c 100644 --- a/src/source/NewUIInventoryCtrl.h +++ b/src/source/NewUIInventoryCtrl.h @@ -159,6 +159,10 @@ namespace SEASON3B void UpdateProcess(); + ITEM* FindItemFromSlotIndex(int slotIndex, bool recoverIfMissing); + void ClearSlotKey(DWORD key); + void RequestInventoryRefresh() const; + bool CheckSlot(int startIndex, int width, int height); bool CheckSlot(int iColumnX, int iRowY, int width, int height); public: @@ -174,6 +178,7 @@ namespace SEASON3B bool AddItem(int iColumnX, int iRowY, BYTE byType, BYTE bySubType, BYTE byLevel = 0, BYTE byDurability = 255, BYTE byOption1 = 0, BYTE byOptionEx = 0, BYTE byOption380 = 0, BYTE byOptionHarmony = 0); void RemoveItem(ITEM* pItem); + bool RemoveItemAt(int iLinealPos); void RemoveAllItems(); size_t GetNumberOfItems(); diff --git a/src/source/NewUIInventoryExtension.cpp b/src/source/NewUIInventoryExtension.cpp index bd725261c..fedb78d5e 100644 --- a/src/source/NewUIInventoryExtension.cpp +++ b/src/source/NewUIInventoryExtension.cpp @@ -290,7 +290,7 @@ bool CNewUIInventoryExtension::InsertItem(int iIndex, std::span pbyI { if (const auto& extension = TryGetExtensionByInventoryIndex(iIndex)) { - extension->AddItem(iIndex, pbyItemPacket); + return extension->AddItem(iIndex, pbyItemPacket); } return false; @@ -300,9 +300,8 @@ void CNewUIInventoryExtension::DeleteItem(int iIndex) const { if (const auto& extension = TryGetExtensionByInventoryIndex(iIndex)) { - if (const auto& pItem = extension->FindItem(iIndex)) + if (extension->RemoveItemAt(iIndex)) { - extension->RemoveItem(pItem); return; } diff --git a/src/source/NewUIMyInventory.cpp b/src/source/NewUIMyInventory.cpp index 74a596a8f..76116f331 100644 --- a/src/source/NewUIMyInventory.cpp +++ b/src/source/NewUIMyInventory.cpp @@ -377,22 +377,19 @@ void CNewUIMyInventory::DeleteItem(int iIndex) const { if (m_pNewInventoryCtrl) { - ITEM* pItem = m_pNewInventoryCtrl->FindItem(iIndex); - if (pItem != nullptr) + if (m_pNewInventoryCtrl->RemoveItemAt(iIndex)) { - m_pNewInventoryCtrl->RemoveItem(pItem); + return; } - else + + CNewUIPickedItem* pPickedItem = CNewUIInventoryCtrl::GetPickedItem(); + if (pPickedItem) { - CNewUIPickedItem* pPickedItem = CNewUIInventoryCtrl::GetPickedItem(); - if (pPickedItem) + if (pPickedItem->GetOwnerInventory() == m_pNewInventoryCtrl) { - if (pPickedItem->GetOwnerInventory() == m_pNewInventoryCtrl) + if (pPickedItem->GetSourceLinealPos() == iIndex) { - if (pPickedItem->GetSourceLinealPos() == iIndex) - { - CNewUIInventoryCtrl::DeletePickedItem(); - } + CNewUIInventoryCtrl::DeletePickedItem(); } } } diff --git a/src/source/WSclient.cpp b/src/source/WSclient.cpp index 2a95c4202..be868af90 100644 --- a/src/source/WSclient.cpp +++ b/src/source/WSclient.cpp @@ -5668,6 +5668,18 @@ void ReceiveDeleteItemViewport(const BYTE* ReceiveBuffer) static const BYTE NOT_GET_ITEM = 0xff; static const BYTE GET_ITEM_ZEN = 0xfe; static const BYTE GET_ITEM_MULTI = 0xfd; // received when item was added in a stack + +namespace +{ + void RequestInventorySync() + { + if (SocketClient != nullptr && SocketClient->ToGameServer() != nullptr) + { + SocketClient->ToGameServer()->SendInventoryRequest(); + } + } +} + extern int ItemKey; void ReceiveGetItem(std::span ReceiveBuffer) { @@ -5707,6 +5719,7 @@ void ReceiveGetItem(std::span ReceiveBuffer) else { auto pickedItem = &Items[ItemKey].Item; + bool shouldResyncInventory = false; auto itemIndex = Data->Value; if (itemIndex != GET_ITEM_MULTI) { @@ -5727,6 +5740,10 @@ void ReceiveGetItem(std::span ReceiveBuffer) { pickedItem = g_pMyInventory->FindItem(itemIndex); } + else + { + shouldResyncInventory = true; + } } else if (IsInventoryExtensionSlot(itemIndex)) { @@ -5734,9 +5751,18 @@ void ReceiveGetItem(std::span ReceiveBuffer) { pickedItem = g_pMyInventoryExt->FindItem(itemIndex); } + else + { + shouldResyncInventory = true; + } } } + if (shouldResyncInventory) + { + RequestInventorySync(); + } + wchar_t szItem[64] = { 0, }; int level = pickedItem->Level; GetItemName(pickedItem->Type, level, szItem); @@ -5832,6 +5858,7 @@ BOOL ReceiveEquipmentItemExtended(std::span ReceiveBuffer) SEASON3B::CNewUIInventoryCtrl::DeletePickedItem(); int itemindex = Data->Index; + bool shouldResyncInventory = false; if (itemindex >= 0 && itemindex < MAX_EQUIPMENT_INDEX) { @@ -5841,17 +5868,22 @@ BOOL ReceiveEquipmentItemExtended(std::span ReceiveBuffer) { g_pStorageInventory->ProcessStorageItemAutoMoveSuccess(); g_pStorageInventoryExt->ProcessStorageItemAutoMoveSuccess(); - g_pMyInventory->InsertItem(itemindex, itemData); + shouldResyncInventory = !g_pMyInventory->InsertItem(itemindex, itemData); } else if (IsInventoryExtensionSlot(itemindex)) { g_pStorageInventory->ProcessStorageItemAutoMoveSuccess(); g_pStorageInventoryExt->ProcessStorageItemAutoMoveSuccess(); - g_pMyInventoryExt->InsertItem(itemindex, itemData); + shouldResyncInventory = !g_pMyInventoryExt->InsertItem(itemindex, itemData); } else if (IsMyShopSlot(itemindex)) { - g_pMyShopInventory->InsertItem(itemindex, itemData); + shouldResyncInventory = !g_pMyShopInventory->InsertItem(itemindex, itemData); + } + + if (shouldResyncInventory) + { + RequestInventorySync(); } } else if (storageType == STORAGE_TYPE::TRADE) @@ -5929,18 +5961,28 @@ void ReceiveModifyItemExtended(std::span ReceiveBuffer) } int itemindex = Data->Index; - if (g_pMyInventory->FindItem(itemindex)) + if (IsMainInventorySlot(itemindex) && g_pMyInventory->FindItem(itemindex)) { g_pMyInventory->DeleteItem(itemindex); } + else if (IsInventoryExtensionSlot(itemindex) && g_pMyInventoryExt->FindItem(itemindex)) + { + g_pMyInventoryExt->DeleteItem(itemindex); + } + bool shouldResyncInventory = false; if (IsMainInventorySlot(itemindex)) { - g_pMyInventory->InsertItem(itemindex, itemData); + shouldResyncInventory = !g_pMyInventory->InsertItem(itemindex, itemData); } else if (IsInventoryExtensionSlot(itemindex)) { - g_pMyInventoryExt->InsertItem(itemindex, itemData); + shouldResyncInventory = !g_pMyInventoryExt->InsertItem(itemindex, itemData); + } + + if (shouldResyncInventory) + { + RequestInventorySync(); } int iType = Items[itemindex].Item.Type; @@ -6695,6 +6737,10 @@ void ReceiveDurability(const BYTE* ReceiveBuffer) else { ITEM* pItem = g_pMyInventory->FindItem(Data->Value); + if (pItem == nullptr && IsInventoryExtensionSlot(Data->Value)) + { + pItem = g_pMyInventoryExt->FindItem(Data->Value); + } if (pItem) {