From baa1cd65c5439aa6bde24cf97bc267b00cdf27b7 Mon Sep 17 00:00:00 2001 From: ephphatha Date: Thu, 23 Sep 2021 23:50:39 +1000 Subject: [PATCH] Make FindGetItem return an index into ActiveItems This allows the calling code in DeltaLoadLevel to behave the same as every other use of DeleteItem, making it possible to remove the duplicate argument and ensure that the ActiveItems/AvailableItems arrays are treated appropriately. --- Source/inv.cpp | 36 +++++++++++++++--------------------- Source/inv.h | 12 ++++++++++-- Source/items.h | 2 +- Source/msg.cpp | 47 ++++++++++++++++++++++++++--------------------- Source/msg.h | 4 ++-- Source/player.cpp | 2 +- 6 files changed, 55 insertions(+), 48 deletions(-) diff --git a/Source/inv.cpp b/Source/inv.cpp index 8143912d0..bf2f89964 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -1721,37 +1721,26 @@ void AutoGetItem(int pnum, Item *item, int ii) player.HoldItem._itype = ItemType::None; } -int FindGetItem(int idx, uint16_t ci, int iseed) +int FindGetItem(int32_t iseed, _item_indexes idx, uint16_t createInfo) { - if (ActiveItemCount <= 0) - return -1; - - int ii; - int i = 0; - while (true) { - ii = ActiveItems[i]; - if (Items[ii].IDidx == idx && Items[ii]._iSeed == iseed && Items[ii]._iCreateInfo == ci) - break; - - i++; - - if (i >= ActiveItemCount) - return -1; + for (uint8_t i = 0; i < ActiveItemCount; i++) { + auto &item = Items[ActiveItems[i]]; + if (item.KeyAttributesMatch(iseed, idx, createInfo)) { + return i; + } } - return ii; + return -1; } -void SyncGetItem(Point position, int idx, uint16_t ci, int iseed) +void SyncGetItem(Point position, int32_t iseed, _item_indexes idx, uint16_t ci) { // Check what the local client has at the target position int ii = dItem[position.x][position.y] - 1; if (ii >= 0 && ii < MAXITEMS) { // If there was an item there, check that it's the same item as the remote player has - if (Items[ii].IDidx != idx - || Items[ii]._iSeed != iseed - || Items[ii]._iCreateInfo != ci) { + if (Items[ii].KeyAttributesMatch(iseed, idx, ci)) { // Key attributes don't match so we must've desynced, ignore this index and try find a matching item via lookup ii = -1; } @@ -1759,7 +1748,12 @@ void SyncGetItem(Point position, int idx, uint16_t ci, int iseed) if (ii == -1) { // Either there's no item at the expected position or it doesn't match what is being picked up, so look for an item that matches the key attributes - ii = FindGetItem(idx, ci, iseed); + ii = FindGetItem(iseed, idx, ci); + + if (ii != -1) { + // Translate to Items index for CleanupItems, FindGetItem returns an ActiveItems index + ii = ActiveItems[ii]; + } } if (ii == -1) { diff --git a/Source/inv.h b/Source/inv.h index 7a6ccaf15..5bb3a2cbe 100644 --- a/Source/inv.h +++ b/Source/inv.h @@ -161,8 +161,16 @@ void CheckInvScrn(bool isShiftHeld, bool isCtrlHeld); void CheckItemStats(Player &player); void InvGetItem(int pnum, int ii); void AutoGetItem(int pnum, Item *item, int ii); -int FindGetItem(int idx, uint16_t ci, int iseed); -void SyncGetItem(Point position, int idx, uint16_t ci, int iseed); + +/** + * @brief Searches for a dropped item with the same type/createInfo/seed + * @param iseed The value used to initialise the RNG when generating the item + * @param idx The overarching type of the target item + * @param createInfo Flags used to describe the specific subtype of the target item + * @return An index into ActiveItems or -1 if no matching item was found +*/ +int FindGetItem(int32_t iseed, _item_indexes idx, uint16_t ci); +void SyncGetItem(Point position, int32_t iseed, _item_indexes idx, uint16_t ci); bool CanPut(Point position); bool TryInvPut(); int InvPutItem(Player &player, Point position); diff --git a/Source/items.h b/Source/items.h index ae0bd7e6d..f695ecd2d 100644 --- a/Source/items.h +++ b/Source/items.h @@ -367,7 +367,7 @@ struct Item { return IsScroll() && _iSpell == spellId; } - [[nodiscard]] bool KeyAttributesMatch(int32_t seed, _item_indexes itemIndex, uint16_t createInfo) + [[nodiscard]] bool KeyAttributesMatch(int32_t seed, _item_indexes itemIndex, uint16_t createInfo) const { return _iSeed == seed && IDidx == itemIndex && _iCreateInfo == createInfo; } diff --git a/Source/msg.cpp b/Source/msg.cpp index 67a23ff87..57831b651 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -715,14 +715,18 @@ DWORD OnRequestGetItem(const TCmd *pCmd, Player &player) } } - if (ii == -1) { // No item at the target position or the key attributes don't match, so try find a matching item. - ii = FindGetItem(message.wIndx, message.wCI, message.dwSeed); + if (ii == -1) { + // No item at the target position or the key attributes don't match, so try find a matching item. + int activeItemIndex = FindGetItem(message.dwSeed, message.wIndx, message.wCI); + if (activeItemIndex != -1) { + ii = ActiveItems[activeItemIndex]; + } } if (ii != -1) { NetSendCmdGItem2(false, CMD_GETITEM, MyPlayerId, message.bPnum, message); if (message.bPnum != MyPlayerId) - SyncGetItem(position, message.wIndx, message.wCI, message.dwSeed); + SyncGetItem(position, message.dwSeed, message.wIndx, message.wCI); else InvGetItem(MyPlayerId, ii); SetItemRecord(message.dwSeed, message.wCI, message.wIndx); @@ -743,20 +747,20 @@ DWORD OnGetItem(const TCmd *pCmd, int pnum) SendPacket(pnum, &message, sizeof(message)); } else if (IsGItemValid(message)) { const Point position { message.x, message.y }; - int ii = FindGetItem(message.wIndx, message.wCI, message.dwSeed); if (DeltaGetItem(message, message.bLevel)) { if ((currlevel == message.bLevel || message.bPnum == MyPlayerId) && message.bMaster != MyPlayerId) { if (message.bPnum == MyPlayerId) { if (currlevel != message.bLevel) { auto &player = Players[MyPlayerId]; - ii = SyncPutItem(player, player.position.tile, message.wIndx, message.wCI, message.dwSeed, message.bId, message.bDur, message.bMDur, message.bCh, message.bMCh, message.wValue, message.dwBuff, message.wToHit, message.wMaxDam, message.bMinStr, message.bMinMag, message.bMinDex, message.bAC); + int ii = SyncPutItem(player, player.position.tile, message.wIndx, message.wCI, message.dwSeed, message.bId, message.bDur, message.bMDur, message.bCh, message.bMCh, message.wValue, message.dwBuff, message.wToHit, message.wMaxDam, message.bMinStr, message.bMinMag, message.bMinDex, message.bAC); if (ii != -1) InvGetItem(MyPlayerId, ii); } else { - InvGetItem(MyPlayerId, ii); + int activeItemIndex = FindGetItem(message.dwSeed, message.wIndx, message.wCI); + InvGetItem(MyPlayerId, ActiveItems[activeItemIndex]); } } else { - SyncGetItem(position, message.wIndx, message.wCI, message.dwSeed); + SyncGetItem(position, message.dwSeed, message.wIndx, message.wCI); } } } else { @@ -788,11 +792,10 @@ DWORD OnRequestAutoGetItem(const TCmd *pCmd, Player &player) if (gbBufferMsgs != 1 && IOwnLevel(player.plrlevel) && IsGItemValid(message)) { const Point position { message.x, message.y }; if (GetItemRecord(message.dwSeed, message.wCI, message.wIndx)) { - int ii = FindGetItem(message.wIndx, message.wCI, message.dwSeed); - if (ii != -1) { + if (FindGetItem(message.dwSeed, message.wIndx, message.wCI) != -1) { NetSendCmdGItem2(false, CMD_AGETITEM, MyPlayerId, message.bPnum, message); if (message.bPnum != MyPlayerId) - SyncGetItem(position, message.wIndx, message.wCI, message.dwSeed); + SyncGetItem(position, message.dwSeed, message.wIndx, message.wCI); else AutoGetItem(MyPlayerId, &Items[message.bCursitem], message.bCursitem); SetItemRecord(message.dwSeed, message.wCI, message.wIndx); @@ -825,7 +828,7 @@ DWORD OnAutoGetItem(const TCmd *pCmd, int pnum) AutoGetItem(MyPlayerId, &Items[message.bCursitem], message.bCursitem); } } else { - SyncGetItem(position, message.wIndx, message.wCI, message.dwSeed); + SyncGetItem(position, message.dwSeed, message.wIndx, message.wCI); } } } else { @@ -843,10 +846,11 @@ DWORD OnItemExtra(const TCmd *pCmd, int pnum) if (gbBufferMsgs == 1) { SendPacket(pnum, &message, sizeof(message)); } else if (IsGItemValid(message)) { - const Point position { message.x, message.y }; DeltaGetItem(message, message.bLevel); - if (currlevel == Players[pnum].plrlevel) - SyncGetItem(position, message.wIndx, message.wCI, message.dwSeed); + if (currlevel == Players[pnum].plrlevel) { + const Point position { message.x, message.y }; + SyncGetItem(position, message.dwSeed, message.wIndx, message.wCI); + } } return sizeof(message); @@ -2223,14 +2227,15 @@ void DeltaLoadLevel() continue; if (sgLevels[currlevel].item[i].bCmd == CMD_WALKXY) { - int ii = FindGetItem( + int activeItemIndex = FindGetItem( + sgLevels[currlevel].item[i].dwSeed, sgLevels[currlevel].item[i].wIndx, - sgLevels[currlevel].item[i].wCI, - sgLevels[currlevel].item[i].dwSeed); - if (ii != -1) { - if (dItem[Items[ii].position.x][Items[ii].position.y] == ii + 1) - dItem[Items[ii].position.x][Items[ii].position.y] = 0; - DeleteItem(ii, i); + sgLevels[currlevel].item[i].wCI); + if (activeItemIndex != -1) { + const auto &position = Items[ActiveItems[activeItemIndex]].position; + if (dItem[position.x][position.y] == ActiveItems[activeItemIndex] + 1) + dItem[position.x][position.y] = 0; + DeleteItem(ActiveItems[activeItemIndex], activeItemIndex); } } if (sgLevels[currlevel].item[i].bCmd == CMD_ACK_PLRINFO) { diff --git a/Source/msg.h b/Source/msg.h index f01a928aa..1d3652d82 100644 --- a/Source/msg.h +++ b/Source/msg.h @@ -230,7 +230,7 @@ struct TCmdGItem { uint8_t bLevel; uint8_t x; uint8_t y; - uint16_t wIndx; + _item_indexes wIndx; uint16_t wCI; int32_t dwSeed; uint8_t bId; @@ -256,7 +256,7 @@ struct TCmdPItem { _cmd_id bCmd; uint8_t x; uint8_t y; - uint16_t wIndx; + _item_indexes wIndx; uint16_t wCI; /** * Item identifier diff --git a/Source/player.cpp b/Source/player.cpp index f516d4a7f..be6bcb1d3 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -3022,7 +3022,7 @@ StartPlayerKill(int pnum, int earflag) ear._iSeed = player._pName[2] << 24 | player._pName[3] << 16 | player._pName[4] << 8 | player._pName[5]; ear._ivalue = player._pLevel; - if (FindGetItem(IDI_EAR, ear._iCreateInfo, ear._iSeed) == -1) { + if (FindGetItem(ear._iSeed, IDI_EAR, ear._iCreateInfo) == -1) { DeadItem(player, &ear, { 0, 0 }); } } else {