fix(savedata): skip bookshelf read on pre-G1 clients

Bookshelf was introduced after Forward.5 (verified: F5 mhfo.dll has no
Bookshelf symbols, modern clients export .?AVBookshelfForm@@). For
F4/F5/S6 the configured pointers place the bookshelf region past the
end of the smaller save blob, causing a slice-bounds panic on every
MSG_MHF_SAVEDATA and rolling characters back to creation state. The
read is now bounds-checked and skipped when absent; bookshelf state
is persisted via house packets into user_binary.bookshelf, so leaving
BookshelfData nil is safe.
This commit is contained in:
Houmgaor
2026-04-07 21:56:40 +02:00
parent 44fd637a59
commit 538724e6c9
2 changed files with 11 additions and 1 deletions

View File

@@ -188,7 +188,16 @@ func (save *CharacterSaveData) updateStructWithSaveData() {
save.RP = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pRP] : save.Pointers[pRP]+saveFieldRP])
save.HouseTier = save.decompSave[save.Pointers[pHouseTier] : save.Pointers[pHouseTier]+saveFieldHouseTier]
save.HouseData = save.decompSave[save.Pointers[pHouseData] : save.Pointers[pHouseData]+saveFieldHouseData]
save.BookshelfData = save.decompSave[save.Pointers[pBookshelfData] : save.Pointers[pBookshelfData]+save.Pointers[lBookshelfData]]
// Bookshelf was introduced after Forward.5 (verified: F5 mhfo.dll
// contains no Bookshelf symbols, while modern clients export
// .?AVBookshelfForm@@). For F4/F5/S6 the configured pointers
// place the bookshelf region past the end of the save blob, so
// skip the read entirely on those versions. Bookshelf state is
// persisted via house packets into user_binary.bookshelf, not
// from this blob, so leaving BookshelfData nil is safe.
if bsEnd := save.Pointers[pBookshelfData] + save.Pointers[lBookshelfData]; bsEnd <= len(save.decompSave) {
save.BookshelfData = save.decompSave[save.Pointers[pBookshelfData]:bsEnd]
}
save.GalleryData = save.decompSave[save.Pointers[pGalleryData] : save.Pointers[pGalleryData]+saveFieldGallery]
save.ToreData = save.decompSave[save.Pointers[pToreData] : save.Pointers[pToreData]+saveFieldTore]
save.GardenData = save.decompSave[save.Pointers[pGardenData] : save.Pointers[pGardenData]+saveFieldGarden]