fix(festa): filter trials and rewards for Forward.5 compatibility (#156)

Skip trials referencing monsters added after em106 (Odibatorasu, the
last F5 monster) and filter out item 7011 which does not exist before
G1, preventing client crashes on Forward.4/5 servers.

Also logs the pre-existing bookshelf save data pointer fix (already
applied during the savedata refactor) in the CHANGELOG.
This commit is contained in:
Houmgaor
2026-03-18 23:19:25 +01:00
parent 4fa6d5b05e
commit a6025be8b7
2 changed files with 29 additions and 1 deletions

View File

@@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed guild nil panics: added nil guards for alliance guild lookups ([#171](https://github.com/Mezeporta/Erupe/issues/171))
- Fixed `rasta_id=0` overwriting NULL in mercenary save, preventing game state saving ([#163](https://github.com/Mezeporta/Erupe/issues/163))
- Fixed false race condition in `PacketDuringLogout` test
- Fixed bookshelf save data pointers for non-ZZ client versions (G1G10, F4F5, S6.0)
- Fixed Forward.5 festa crashes: skip trials referencing monsters added after em106 (Odibatorasu) and filter out item 7011 which does not exist before G1 ([#156](https://github.com/Mezeporta/Erupe/pull/156))
### Changed

View File

@@ -212,6 +212,21 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
if err != nil {
s.logger.Error("Failed to query festa trials", zap.Error(err))
}
// em106 (Odibatorasu) is the last monster added in Forward.5; skip trials
// referencing monsters or items that don't exist in that version.
if s.server.erupeConfig.RealClientMode <= cfg.F5 {
filtered := trials[:0]
for _, t := range trials {
if (t.Objective == 1 || t.Objective == 2 || t.Objective == 3) && t.GoalID > 106 {
continue
}
if t.Objective == 4 && t.GoalID > 6430 {
continue
}
filtered = append(filtered, t)
}
trials = filtered
}
bf.WriteUint16(uint16(len(trials)))
for _, trial := range trials {
bf.WriteUint32(trial.ID)
@@ -227,7 +242,6 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
}
// The Winner and Loser Armor IDs are missing
// Item 7011 may not exist in older versions, remove to prevent crashes
// Fields: {Unk0, Unk1, ItemType, Quantity, ItemID, MinHR, MinSR, MinGR}
rewards := []FestaReward{
{1, 0, 7, 350, 1520, 0, 0, 0},
@@ -257,6 +271,18 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
//{5, 0, 1, 0, 0, 0, 0, 0},
}
// Item 7011 does not exist before G1 — filter it to prevent client crashes.
if s.server.erupeConfig.RealClientMode <= cfg.F5 {
filtered := rewards[:0]
for _, r := range rewards {
if r.ItemType == 7 && r.ItemID == 7011 {
continue
}
filtered = append(filtered, r)
}
rewards = filtered
}
bf.WriteUint16(uint16(len(rewards)))
for _, reward := range rewards {
bf.WriteUint8(reward.Unk0)