From 88af4375bf04c4e651bccf606d02ca8a90f4372e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=82ngelo=20Tadeucci?= Date: Wed, 7 Oct 2026 13:07:42 -0300 Subject: [PATCH] Parse string//titlename.xml as its own table ParseTitleTag only returns names for ids that have a titletag.xml row, and the client builds its profile title dropdown from titlename.xml alone. The server needs every title the client can name, after the locale and feature filter, to stop sending titles the dropdown cannot show. Co-Authored-By: Claude Opus 5.5 (1M context) --- Maple2.File.Parser/Maple2.File.Parser.csproj | 2 +- Maple2.File.Parser/TableParser.cs | 12 ++++++++++++ Maple2.File.Tests/TableParserTest.cs | 12 ++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Maple2.File.Parser/Maple2.File.Parser.csproj b/Maple2.File.Parser/Maple2.File.Parser.csproj index f275388..985a1a1 100644 --- a/Maple2.File.Parser/Maple2.File.Parser.csproj +++ b/Maple2.File.Parser/Maple2.File.Parser.csproj @@ -13,7 +13,7 @@ MapleStory2, File, Parser, m2d, xml true - 2.4.27 + 2.4.28 net8.0 README.md enable diff --git a/Maple2.File.Parser/TableParser.cs b/Maple2.File.Parser/TableParser.cs index bff97b4..b058a08 100644 --- a/Maple2.File.Parser/TableParser.cs +++ b/Maple2.File.Parser/TableParser.cs @@ -882,6 +882,18 @@ public IEnumerable ParseJobTableNew() { } } + // One entry per title id that survives the feature and locale filter, which is also the set the + // client can name. A title missing here shows no row in the client's title dropdown. + public IEnumerable<(int Id, string Name)> ParseTitleName() { + XmlReader reader = xmlReader.GetXmlReader(xmlReader.GetEntry($"{language}/titlename.xml")); + var mapping = nameSerializer.Deserialize(reader) as StringMapping; + Debug.Assert(mapping != null); + + foreach (Key key in mapping.key) { + yield return (int.Parse(key.id), key.name); + } + } + public IEnumerable<(int Id, IDictionary>)> ParseIndividualItemDrop() { string xml = Sanitizer.RemoveEmpty(xmlReader.GetString(xmlReader.GetEntry("table/individualitemdrop.xml"))); xml = Sanitizer.SanitizeBool(xml); diff --git a/Maple2.File.Tests/TableParserTest.cs b/Maple2.File.Tests/TableParserTest.cs index 78ab3a6..4dd9b30 100644 --- a/Maple2.File.Tests/TableParserTest.cs +++ b/Maple2.File.Tests/TableParserTest.cs @@ -396,6 +396,18 @@ public void TestParseTitleTag() { } } + [TestMethod] + public void TestParseTitleName() { + Dictionary names = _parser.ParseTitleName().ToDictionary(entry => entry.Id, entry => entry.Name); + + // Rows of titlename.xml, read against feature.xml under Live NA. + Assert.AreEqual("Ace Archer", names[10000655]); + // feature="Fame_Geo01", which is NA="99". + Assert.IsFalse(names.ContainsKey(10000754)); + // locale="CN" only. + Assert.IsFalse(names.ContainsKey(10000750)); + } + [TestMethod] public void TestIndividualItemDrop() { foreach ((_, _) in _parser.ParseIndividualItemDrop()) {