From b308c86f47d77738c167c764e8d4e2cef2fd40eb Mon Sep 17 00:00:00 2001 From: Zin <62830952+Zintixx@users.noreply.github.com> Date: Tue, 27 Oct 2026 21:21:39 -0700 Subject: [PATCH 1/2] Parse table/Server/shadowExpeditionDrop.xml Co-Authored-By: Claude Opus 5.5 --- Maple2.File.Parser/Maple2.File.Parser.csproj | 2 +- Maple2.File.Parser/ServerTableParser.cs | 13 +++++++++++++ .../Xml/Table/Server/ShadowExpeditionDrop.cs | 17 +++++++++++++++++ Maple2.File.Tests/ServerTableParserTest.cs | 19 +++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 Maple2.File.Parser/Xml/Table/Server/ShadowExpeditionDrop.cs diff --git a/Maple2.File.Parser/Maple2.File.Parser.csproj b/Maple2.File.Parser/Maple2.File.Parser.csproj index 73d6e43..45eca3a 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.31 + 2.4.32 net8.0 README.md enable diff --git a/Maple2.File.Parser/ServerTableParser.cs b/Maple2.File.Parser/ServerTableParser.cs index 3b5cecc..2a1e101 100644 --- a/Maple2.File.Parser/ServerTableParser.cs +++ b/Maple2.File.Parser/ServerTableParser.cs @@ -43,6 +43,7 @@ public class ServerTableParser { private readonly XmlSerializer spawnNpcSerializer; private readonly XmlSerializer spawnInteractObjectSerializer; private readonly XmlSerializer groupSpawnSerializer; + private readonly XmlSerializer shadowExpeditionDropSerializer; private readonly XmlSerializer fishSerializer; private readonly XmlSerializer fishingSpotSerializer; private readonly XmlSerializer fishLureSerializer; @@ -91,6 +92,7 @@ public ServerTableParser(M2dReader xmlReader) { spawnNpcSerializer = new XmlSerializer(typeof(SpawnNpcRoot)); spawnInteractObjectSerializer = new XmlSerializer(typeof(SpawnInteractObjectRoot)); groupSpawnSerializer = new XmlSerializer(typeof(GroupSpawnRoot)); + shadowExpeditionDropSerializer = new XmlSerializer(typeof(ShadowExpeditionDropRoot)); fishSerializer = new XmlSerializer(typeof(FishRoot)); fishingSpotSerializer = new XmlSerializer(typeof(FishingSpotRoot)); fishLureSerializer = new XmlSerializer(typeof(FishLureRoot)); @@ -511,6 +513,17 @@ public ServerTableParser(M2dReader xmlReader) { } } + public IEnumerable ParseShadowExpeditionDrop() { + string xml = Sanitizer.RemoveEmpty(xmlReader.GetString(xmlReader.GetEntry("table/Server/shadowExpeditionDrop.xml"))); + var reader = XmlReader.Create(new StringReader(xml)); + var data = shadowExpeditionDropSerializer.Deserialize(reader) as ShadowExpeditionDropRoot; + Debug.Assert(data != null); + + foreach (ShadowExpeditionDrop drop in data.shadowExpeditionDrop) { + yield return drop; + } + } + public IEnumerable<(int Id, Fish Fish)> ParseFish() { string xml = Sanitizer.RemoveEmpty(xmlReader.GetString(xmlReader.GetEntry("table/Server/fish.xml"))); var reader = XmlReader.Create(new StringReader(xml)); diff --git a/Maple2.File.Parser/Xml/Table/Server/ShadowExpeditionDrop.cs b/Maple2.File.Parser/Xml/Table/Server/ShadowExpeditionDrop.cs new file mode 100644 index 0000000..a4d2c27 --- /dev/null +++ b/Maple2.File.Parser/Xml/Table/Server/ShadowExpeditionDrop.cs @@ -0,0 +1,17 @@ +using System.Xml.Serialization; +using M2dXmlGenerator; + +namespace Maple2.File.Parser.Xml.Table.Server; + +// ./data/server/table/Server/shadowExpeditionDrop.xml +[XmlRoot("ms2")] +public class ShadowExpeditionDropRoot { + [XmlElement] public List shadowExpeditionDrop; +} + +// class is the killed NPC's basic class: 1 normal, 3 elite, 6 boss. +public partial class ShadowExpeditionDrop { + [XmlAttribute] public int step; + [XmlAttribute("class")] public int npcClass; + [M2dArray] public int[] dropBoxId = Array.Empty(); +} diff --git a/Maple2.File.Tests/ServerTableParserTest.cs b/Maple2.File.Tests/ServerTableParserTest.cs index 5a84fd0..64b2b7b 100644 --- a/Maple2.File.Tests/ServerTableParserTest.cs +++ b/Maple2.File.Tests/ServerTableParserTest.cs @@ -265,6 +265,25 @@ public void TestGroupSpawn() { } } + [TestMethod] + public void TestShadowExpeditionDrop() { + var parser = new ServerTableParser(TestUtils.ServerReader); + + List drops = parser.ParseShadowExpeditionDrop().ToList(); + Assert.AreEqual(102, drops.Count); + + // + Assert.AreEqual(1, drops[0].step); + Assert.AreEqual(1, drops[0].npcClass); + CollectionAssert.AreEqual(new[] { 920001001 }, drops[0].dropBoxId); + + // + ShadowExpeditionDrop last = drops[^1]; + Assert.AreEqual(34, last.step); + Assert.AreEqual(6, last.npcClass); + CollectionAssert.AreEqual(new[] { 920001002, 920006034, 920000034, 820000034 }, last.dropBoxId); + } + [TestMethod] public void TestSpawnInteractObject() { var parser = new ServerTableParser(TestUtils.ServerReader); From 7931fa493cf3f850c39df88169e5705e71f17d6c Mon Sep 17 00:00:00 2001 From: Zin <62830952+Zintixx@users.noreply.github.com> Date: Tue, 27 Oct 2026 21:25:38 -0700 Subject: [PATCH 2/2] Name the class attribute as Npc/Basic does and test a class-3 row Co-Authored-By: Claude Opus 5.5 --- .../Xml/Table/Server/ShadowExpeditionDrop.cs | 4 ++-- Maple2.File.Tests/ServerTableParserTest.cs | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Maple2.File.Parser/Xml/Table/Server/ShadowExpeditionDrop.cs b/Maple2.File.Parser/Xml/Table/Server/ShadowExpeditionDrop.cs index a4d2c27..cf8d135 100644 --- a/Maple2.File.Parser/Xml/Table/Server/ShadowExpeditionDrop.cs +++ b/Maple2.File.Parser/Xml/Table/Server/ShadowExpeditionDrop.cs @@ -9,9 +9,9 @@ public class ShadowExpeditionDropRoot { [XmlElement] public List shadowExpeditionDrop; } -// class is the killed NPC's basic class: 1 normal, 3 elite, 6 boss. public partial class ShadowExpeditionDrop { [XmlAttribute] public int step; - [XmlAttribute("class")] public int npcClass; + // The killed NPC's basic class: 1, 3 or 6, the classes whose npc rankIcon is c, b and a (normal, elite, boss). + [XmlAttribute("class")] public int @class; [M2dArray] public int[] dropBoxId = Array.Empty(); } diff --git a/Maple2.File.Tests/ServerTableParserTest.cs b/Maple2.File.Tests/ServerTableParserTest.cs index 64b2b7b..979f80e 100644 --- a/Maple2.File.Tests/ServerTableParserTest.cs +++ b/Maple2.File.Tests/ServerTableParserTest.cs @@ -274,13 +274,18 @@ public void TestShadowExpeditionDrop() { // Assert.AreEqual(1, drops[0].step); - Assert.AreEqual(1, drops[0].npcClass); + Assert.AreEqual(1, drops[0].@class); CollectionAssert.AreEqual(new[] { 920001001 }, drops[0].dropBoxId); + // + Assert.AreEqual(1, drops[1].step); + Assert.AreEqual(3, drops[1].@class); + CollectionAssert.AreEqual(new[] { 920001002, 920003001 }, drops[1].dropBoxId); + // ShadowExpeditionDrop last = drops[^1]; Assert.AreEqual(34, last.step); - Assert.AreEqual(6, last.npcClass); + Assert.AreEqual(6, last.@class); CollectionAssert.AreEqual(new[] { 920001002, 920006034, 920000034, 820000034 }, last.dropBoxId); }