feat(net): #13 read OptionFlags + Options1 after enchantments

First step of the PD trailer walk. Wraps trailer reads in their own
try/catch so a malformed trailer does not null out the upstream
attribute/skill/spell/enchantment data we already extracted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-10 08:18:38 +02:00
parent 65870349a8
commit becbde60a4
2 changed files with 59 additions and 14 deletions

View file

@ -334,4 +334,33 @@ public sealed class PlayerDescriptionParserTests
Assert.Equal(2.0f, parsed.Value.Spells[1234u]);
Assert.Equal(2.0f, parsed.Value.Spells[5678u]);
}
[Fact]
public void TryParse_TrailerOptionFlagsAndOptions1_AreReadAfterEnchantments()
{
// ATTRIBUTE | ENCHANTMENT vector flag; empty enchantment mask (0).
// After mask, trailer adds u32 option_flags + u32 options1.
var sb = new MemoryStream();
using var writer = new BinaryWriter(sb);
writer.Write(0u); // propertyFlags
writer.Write(0x52u); // weenieType
writer.Write(0x201u); // ATTRIBUTE | ENCHANTMENT
writer.Write(1u); // has_health
writer.Write(0u); // empty attribute_flags
writer.Write(0u); // EnchantmentMask = empty
// Trailer header: option_flags + options1
writer.Write(0u); // option_flags = None — no further sections
writer.Write(0xDEADBEEFu); // options1 sentinel
// No more bytes — spellbook_filters is optional (defaults to 0).
var parsed = PlayerDescriptionParser.TryParse(sb.ToArray());
Assert.NotNull(parsed);
Assert.Equal(PlayerDescriptionParser.CharacterOptionDataFlag.None, parsed!.Value.OptionFlags);
Assert.Equal(0xDEADBEEFu, parsed.Value.Options1);
Assert.Empty(parsed.Value.Shortcuts);
Assert.Empty(parsed.Value.Inventory);
}
}