Browse Source

Resolve game crash when syncing Diablo items in Hellfire games

pull/3965/head
staphen 4 years ago committed by Anders Jenbo
parent
commit
b85485b8f3
  1. 2
      Source/items.cpp
  2. 2
      Source/multi.cpp
  3. 18
      Source/pack.cpp
  4. 4
      Source/pack.h
  5. 4
      Source/pfile.cpp
  6. 16
      test/pack_test.cpp

2
Source/items.cpp

@ -3442,7 +3442,7 @@ void CornerstoneSave()
return;
if (!CornerStone.item.isEmpty()) {
ItemPack id;
PackItem(id, CornerStone.item);
PackItem(id, CornerStone.item, (CornerStone.item.dwBuff & CF_HELLFIRE) != 0);
const auto *buffer = reinterpret_cast<uint8_t *>(&id);
for (size_t i = 0; i < sizeof(ItemPack); i++) {
snprintf(&sgOptions.Hellfire.szItem[i * 2], 3, "%02hhX", buffer[i]);

2
Source/multi.cpp

@ -320,7 +320,7 @@ void SendPlayerInfo(int pnum, _cmd_id cmd)
static_assert(alignof(PlayerPack) == 1, "Fix pkplr alignment");
std::unique_ptr<byte[]> pkplr { new byte[sizeof(PlayerPack)] };
PackPlayer(reinterpret_cast<PlayerPack *>(pkplr.get()), Players[MyPlayerId], true);
PackPlayer(reinterpret_cast<PlayerPack *>(pkplr.get()), Players[MyPlayerId], true, true);
dthread_send_delta(pnum, cmd, std::move(pkplr), sizeof(PlayerPack));
}

18
Source/pack.cpp

@ -35,14 +35,14 @@ void VerifyGoldSeeds(Player &player)
} // namespace
void PackItem(ItemPack &packedItem, const Item &item)
void PackItem(ItemPack &packedItem, const Item &item, bool isHellfire)
{
packedItem = {};
if (item.isEmpty()) {
packedItem.idx = 0xFFFF;
} else {
auto idx = item.IDidx;
if (!gbIsHellfire) {
if (!isHellfire) {
idx = RemapItemIdxToDiablo(idx);
}
if (gbIsSpawn) {
@ -74,7 +74,7 @@ void PackItem(ItemPack &packedItem, const Item &item)
}
}
void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield)
void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield, bool netSync)
{
memset(pPack, 0, sizeof(*pPack));
pPack->destAction = player.destAction;
@ -109,19 +109,25 @@ void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield)
pPack->pSplLvl2[i - 37] = player._pSplLvl[i];
for (int i = 0; i < NUM_INVLOC; i++) {
PackItem(pPack->InvBody[i], player.InvBody[i]);
const Item &item = player.InvBody[i];
bool isHellfire = netSync ? ((item.dwBuff & CF_HELLFIRE) != 0) : gbIsHellfire;
PackItem(pPack->InvBody[i], item, isHellfire);
}
pPack->_pNumInv = player._pNumInv;
for (int i = 0; i < pPack->_pNumInv; i++) {
PackItem(pPack->InvList[i], player.InvList[i]);
const Item &item = player.InvList[i];
bool isHellfire = netSync ? ((item.dwBuff & CF_HELLFIRE) != 0) : gbIsHellfire;
PackItem(pPack->InvList[i], item, isHellfire);
}
for (int i = 0; i < NUM_INV_GRID_ELEM; i++)
pPack->InvGrid[i] = player.InvGrid[i];
for (int i = 0; i < MAXBELTITEMS; i++) {
PackItem(pPack->SpdList[i], player.SpdList[i]);
const Item &item = player.SpdList[i];
bool isHellfire = netSync ? ((item.dwBuff & CF_HELLFIRE) != 0) : gbIsHellfire;
PackItem(pPack->SpdList[i], item, isHellfire);
}
pPack->wReflections = SDL_SwapLE16(player.wReflections);

4
Source/pack.h

@ -79,7 +79,7 @@ struct PlayerPack {
};
#pragma pack(pop)
void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield);
void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield, bool netSync);
bool UnPackPlayer(const PlayerPack *pPack, Player &player, bool netSync);
/**
@ -88,7 +88,7 @@ bool UnPackPlayer(const PlayerPack *pPack, Player &player, bool netSync);
* @param packedItem The destination packed struct
* @param item The source item
*/
void PackItem(ItemPack &packedItem, const Item &item);
void PackItem(ItemPack &packedItem, const Item &item, bool isHellfire);
/**
* Expand a ItemPack in to a Item

4
Source/pfile.cpp

@ -262,7 +262,7 @@ void pfile_write_hero(bool writeGameData, bool clearTables)
PlayerPack pkplr;
auto &myPlayer = Players[MyPlayerId];
PackPlayer(&pkplr, myPlayer, !gbIsMultiplayer);
PackPlayer(&pkplr, myPlayer, !gbIsMultiplayer, false);
EncodeHero(&pkplr);
if (!gbVanilla) {
SaveHotkeys();
@ -342,7 +342,7 @@ bool pfile_ui_save_create(_uiheroinfo *heroinfo)
auto &player = Players[0];
CreatePlayer(0, heroinfo->heroclass);
CopyUtf8(player._pName, heroinfo->name, PLR_NAME_LEN);
PackPlayer(&pkplr, player, true);
PackPlayer(&pkplr, player, true, false);
EncodeHero(&pkplr);
Game2UiPlayer(player, heroinfo, false);
if (!gbVanilla) {

16
test/pack_test.cpp

@ -345,7 +345,7 @@ TEST(PackTest, UnPackItem_diablo)
UnPackItem(PackedDiabloItems[i], id, false);
CompareItems(id, DiabloItems[i]);
PackItem(is, id);
PackItem(is, id, gbIsHellfire);
ComparePackedItems(is, PackedDiabloItems[i]);
}
}
@ -380,7 +380,7 @@ TEST(PackTest, UnPackItem_diablo_unique_bug)
ASSERT_EQ(id.IDidx, IDI_STEELVEIL);
ItemPack is;
PackItem(is, id);
PackItem(is, id, gbIsHellfire);
ComparePackedItems(is, pkItem);
}
@ -416,7 +416,7 @@ TEST(PackTest, UnPackItem_spawn)
UnPackItem(PackedSpawnItems[i], id, false);
CompareItems(id, SpawnItems[i]);
PackItem(is, id);
PackItem(is, id, gbIsHellfire);
ComparePackedItems(is, PackedSpawnItems[i]);
}
}
@ -460,7 +460,7 @@ TEST(PackTest, UnPackItem_diablo_multiplayer)
UnPackItem(PackedDiabloMPItems[i], id, false);
CompareItems(id, DiabloMPItems[i]);
PackItem(is, id);
PackItem(is, id, gbIsHellfire);
ComparePackedItems(is, PackedDiabloMPItems[i]);
}
}
@ -669,7 +669,7 @@ TEST(PackTest, UnPackItem_hellfire)
UnPackItem(PackedHellfireItems[i], id, true);
CompareItems(id, HellfireItems[i]);
PackItem(is, id);
PackItem(is, id, gbIsHellfire);
is.dwBuff &= ~CF_HELLFIRE;
ComparePackedItems(is, PackedHellfireItems[i]);
}
@ -706,7 +706,7 @@ TEST(PackTest, PackItem_empty)
id._itype = ItemType::None;
PackItem(is, id);
PackItem(is, id, gbIsHellfire);
// Copy the value out before comparing to avoid loading a misaligned address.
const auto idx = is.idx;
@ -726,7 +726,7 @@ static void compareGold(const ItemPack &is, int iCurs)
ASSERT_EQ(id._iClass, ICLASS_GOLD);
ItemPack is2;
PackItem(is2, id);
PackItem(is2, id, gbIsHellfire);
ComparePackedItems(is, is2);
}
@ -758,7 +758,7 @@ TEST(PackTest, UnPackItem_ear)
ASSERT_EQ(id._ivalue, 3);
ItemPack is2;
PackItem(is2, id);
PackItem(is2, id, gbIsHellfire);
ComparePackedItems(is, is2);
}

Loading…
Cancel
Save