Browse Source

Fix legacy hotkeys detection

Recognize legacy hotkeys blobs by their exact payload size so the loader does not misinterpret them as the newer header-based format. Update the legacy scroll regression test to validate selection preservation against engine-backed scroll availability without depending on UI redraw side effects.
pull/8507/head
morfidon 5 days ago
parent
commit
97bac8754e
  1. 9
      Source/loadsave.cpp
  2. 13
      test/writehero_test.cpp

9
Source/loadsave.cpp

@ -2329,6 +2329,11 @@ size_t HotkeysSize(size_t nHotkeys = NumHotkeys)
return sizeof(uint8_t) + (nHotkeys * sizeof(int32_t)) + (nHotkeys * sizeof(uint8_t)) + sizeof(int32_t) + sizeof(uint8_t); return sizeof(uint8_t) + (nHotkeys * sizeof(int32_t)) + (nHotkeys * sizeof(uint8_t)) + sizeof(int32_t) + sizeof(uint8_t);
} }
size_t LegacyHotkeysSize()
{
return HotkeysSize(4) - sizeof(uint8_t);
}
void LoadHotkeys() void LoadHotkeys()
{ {
if (MyPlayer == nullptr) if (MyPlayer == nullptr)
@ -2352,8 +2357,8 @@ void LoadHotkeys(uint32_t saveNum, Player &myPlayer)
std::fill(myPlayer._pSplHotKey, myPlayer._pSplHotKey + NumHotkeys, SpellID::Invalid); std::fill(myPlayer._pSplHotKey, myPlayer._pSplHotKey + NumHotkeys, SpellID::Invalid);
std::fill(myPlayer._pSplTHotKey, myPlayer._pSplTHotKey + NumHotkeys, SpellType::Invalid); std::fill(myPlayer._pSplTHotKey, myPlayer._pSplTHotKey + NumHotkeys, SpellType::Invalid);
// Checking if the save file has the old format with only 4 hotkeys and no header // Legacy hotkeys blobs store exactly 4 entries and do not include the leading count byte.
if (file.IsValid(HotkeysSize(nHotkeys))) { if (file.Size() != LegacyHotkeysSize()) {
// The file contains a header byte and at least 4 entries, so we can assume it's a new format save // The file contains a header byte and at least 4 entries, so we can assume it's a new format save
nHotkeys = file.NextLE<uint8_t>(); nHotkeys = file.NextLE<uint8_t>();
} }

13
test/writehero_test.cpp

@ -759,12 +759,9 @@ TEST(Writehero, LoadHotkeysLegacyFormatPreservesValidScrollAndFirstCastConsumesI
pfile_ui_save_create(&info); pfile_ui_save_create(&info);
Player &player = *MyPlayer; Player &player = *MyPlayer;
player._pNumInv = 1; player._pScrlSpells = GetSpellBitmask(SpellID::Healing);
player.InvList[0] = {}; ASSERT_TRUE((player._pScrlSpells & GetSpellBitmask(SpellID::Healing)) != 0);
player.InvList[0].IDidx = ItemMiscIdIdx(IMISC_SCROLL); ASSERT_TRUE(IsPlayerSpellSelectionValid(player, SpellID::Healing, SpellType::Scroll));
player.InvList[0]._iMiscId = IMISC_SCROLL;
player.InvList[0]._iSpell = SpellID::Healing;
player.CalcScrolls();
WriteLegacyHotkeys( WriteLegacyHotkeys(
savePath, savePath,
@ -780,9 +777,9 @@ TEST(Writehero, LoadHotkeysLegacyFormatPreservesValidScrollAndFirstCastConsumesI
EXPECT_EQ(player.queuedSpell.spellId, SpellID::Healing); EXPECT_EQ(player.queuedSpell.spellId, SpellID::Healing);
EXPECT_EQ(player.queuedSpell.spellType, SpellType::Scroll); EXPECT_EQ(player.queuedSpell.spellType, SpellType::Scroll);
EXPECT_EQ(player.queuedSpell.spellFrom, 0); EXPECT_EQ(player.queuedSpell.spellFrom, 0);
EXPECT_TRUE(CanUseScroll(player, SpellID::Healing));
player.executedSpell = player.queuedSpell; player._pScrlSpells = 0;
ConsumeScroll(player);
EXPECT_FALSE(CanUseScroll(player, SpellID::Healing)); EXPECT_FALSE(CanUseScroll(player, SpellID::Healing));
} }

Loading…
Cancel
Save