From b85485b8f30f9727ee3f6ba3693acc40a9691036 Mon Sep 17 00:00:00 2001 From: staphen Date: Sun, 16 Jan 2022 14:41:36 -0500 Subject: [PATCH] Resolve game crash when syncing Diablo items in Hellfire games --- Source/items.cpp | 2 +- Source/multi.cpp | 2 +- Source/pack.cpp | 18 ++++++++++++------ Source/pack.h | 4 ++-- Source/pfile.cpp | 4 ++-- test/pack_test.cpp | 16 ++++++++-------- 6 files changed, 26 insertions(+), 20 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index 89b228ebb..34f04b782 100644 --- a/Source/items.cpp +++ b/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(&id); for (size_t i = 0; i < sizeof(ItemPack); i++) { snprintf(&sgOptions.Hellfire.szItem[i * 2], 3, "%02hhX", buffer[i]); diff --git a/Source/multi.cpp b/Source/multi.cpp index ba0550814..f1feb3879 100644 --- a/Source/multi.cpp +++ b/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 pkplr { new byte[sizeof(PlayerPack)] }; - PackPlayer(reinterpret_cast(pkplr.get()), Players[MyPlayerId], true); + PackPlayer(reinterpret_cast(pkplr.get()), Players[MyPlayerId], true, true); dthread_send_delta(pnum, cmd, std::move(pkplr), sizeof(PlayerPack)); } diff --git a/Source/pack.cpp b/Source/pack.cpp index e8397ab03..e122ed5aa 100644 --- a/Source/pack.cpp +++ b/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); diff --git a/Source/pack.h b/Source/pack.h index 07f176f2a..0141a8117 100644 --- a/Source/pack.h +++ b/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 diff --git a/Source/pfile.cpp b/Source/pfile.cpp index 7ef29a176..1b0b4c4cc 100644 --- a/Source/pfile.cpp +++ b/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) { diff --git a/test/pack_test.cpp b/test/pack_test.cpp index 497b8314f..6b1451e83 100644 --- a/test/pack_test.cpp +++ b/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); }