Browse Source

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.
pull/3586/head
ephphatha 5 years ago committed by Anders Jenbo
parent
commit
baa1cd65c5
  1. 36
      Source/inv.cpp
  2. 12
      Source/inv.h
  3. 2
      Source/items.h
  4. 47
      Source/msg.cpp
  5. 4
      Source/msg.h
  6. 2
      Source/player.cpp

36
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) {

12
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);

2
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;
}

47
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) {

4
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

2
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 {

Loading…
Cancel
Save