diff --git a/Maple2.File.Parser/Maple2.File.Parser.csproj b/Maple2.File.Parser/Maple2.File.Parser.csproj
index b69f6ef..785b24a 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.1.27
+ 2.1.28
net8.0
README.md
enable
diff --git a/Maple2.File.Parser/ServerTableParser.cs b/Maple2.File.Parser/ServerTableParser.cs
index 95a7ab5..9addeb8 100644
--- a/Maple2.File.Parser/ServerTableParser.cs
+++ b/Maple2.File.Parser/ServerTableParser.cs
@@ -43,6 +43,7 @@ public class ServerTableParser {
private readonly XmlSerializer unlimitedEnchantOptionSerializer;
private readonly XmlSerializer itemMergeOptionSerializer;
private readonly XmlSerializer enchantOptionSerializer;
+ private readonly XmlSerializer shopMeretSerializer;
public ServerTableParser(M2dReader xmlReader) {
this.xmlReader = xmlReader;
@@ -79,6 +80,7 @@ public ServerTableParser(M2dReader xmlReader) {
unlimitedEnchantOptionSerializer = new XmlSerializer(typeof(UnlimitedEnchantOptionRoot));
itemMergeOptionSerializer = new XmlSerializer(typeof(ItemMergeOptionRoot));
enchantOptionSerializer = new XmlSerializer(typeof(EnchantOptionRoot));
+ shopMeretSerializer = new XmlSerializer(typeof(ShopMeretRoot));
// var seen = new HashSet();
// this.bankTypeSerializer.UnknownAttribute += (sender, args) => {
@@ -319,6 +321,18 @@ public ServerTableParser(M2dReader xmlReader) {
}
}
+ public IEnumerable<(int ShopId, ShopGame ShopGame)> ParseShopUgc() {
+ string xml = Sanitizer.RemoveEmpty(xmlReader.GetString(xmlReader.GetEntry("table/Server/shop_UGC.xml")));
+ xml = Sanitizer.RemoveSpaces(xml);
+ var reader = XmlReader.Create(new StringReader(xml));
+ var data = shopGameSerializer.Deserialize(reader) as ShopGameRoot;
+ Debug.Assert(data != null);
+
+ foreach (ShopGame shopGame in data.shop) {
+ yield return (shopGame.shopID, shopGame);
+ }
+ }
+
public IEnumerable<(int ShopId, ShopBeauty ShopBeauty)> ParseShopBeauty() {
XmlReader reader = xmlReader.GetXmlReader(xmlReader.GetEntry("table/Server/NA/shop_beauty.xml"));
var data = shopBeautySerializer.Deserialize(reader) as ShopBeautyRoot;
@@ -602,4 +616,15 @@ public ServerTableParser(M2dReader xmlReader) {
yield return (entry.id, entry);
}
}
+
+ public IEnumerable<(int Sn, ShopMeret ShopMeret)> ParseShopMeret() {
+ string xml = Sanitizer.RemoveEmpty(xmlReader.GetString(xmlReader.GetEntry("table/Server/shop_merat.xml")));
+ var reader = XmlReader.Create(new StringReader(xml));
+ var data = shopMeretSerializer.Deserialize(reader) as ShopMeretRoot;
+ Debug.Assert(data != null);
+
+ foreach (ShopMeret shopMeret in data.item) {
+ yield return (shopMeret.sn, shopMeret);
+ }
+ }
}
diff --git a/Maple2.File.Parser/Tools/Sanitizer.cs b/Maple2.File.Parser/Tools/Sanitizer.cs
index 1b1350c..323a186 100644
--- a/Maple2.File.Parser/Tools/Sanitizer.cs
+++ b/Maple2.File.Parser/Tools/Sanitizer.cs
@@ -86,6 +86,10 @@ public static string RemoveEmpty(string xml) {
return Regex.Replace(xml, "\\w+=\"\"", string.Empty);
}
+ public static string RemoveSpaces(string xml) {
+ return Regex.Replace(xml, "(\\w+)=\"([^\"]*?)\\s+\"", "$1=\"$2\"");
+ }
+
// Floats using ',' are converted to '.' (1,2 -> 1.2)
private static string FixCommaFloats(string xml, params string[] attributes) {
string pattern = $"({string.Join('|', attributes)})=\"(-?\\d+)(?:,(\\d+))\"";
diff --git a/Maple2.File.Parser/Xml/Table/Server/ShopMeret.cs b/Maple2.File.Parser/Xml/Table/Server/ShopMeret.cs
new file mode 100644
index 0000000..7c1f48d
--- /dev/null
+++ b/Maple2.File.Parser/Xml/Table/Server/ShopMeret.cs
@@ -0,0 +1,31 @@
+using System.Xml.Serialization;
+
+namespace Maple2.File.Parser.Xml.Table.Server;
+
+// ./data/server/table/Server/shop_merat.xml
+[XmlRoot("ms2")]
+public class ShopMeretRoot {
+ [XmlElement] public List item;
+}
+
+public partial class ShopMeret {
+ [XmlAttribute] public int sn;
+ [XmlAttribute] public int id;
+ [XmlAttribute] public string category = string.Empty;
+ [XmlAttribute] public long price;
+ [XmlAttribute] public long price_1;
+ [XmlAttribute] public long price_7;
+ [XmlAttribute] public long price_30;
+ [XmlAttribute] public long salePrice;
+ [XmlAttribute] public long salePrice_1;
+ [XmlAttribute] public long salePrice_7;
+ [XmlAttribute] public long salePrice_30;
+ [XmlAttribute] public int defPriceIndex;
+ [XmlAttribute] public short grade;
+ [XmlAttribute] public int saleTag;
+ [XmlAttribute] public bool visible;
+ [XmlAttribute] public string createDate = string.Empty;
+ [XmlAttribute] public int chartOrder;
+ [XmlAttribute] public int buyLimit;
+ [XmlAttribute] public int buyLimitMax;
+}
diff --git a/Maple2.File.Tests/ServerTableParserTest.cs b/Maple2.File.Tests/ServerTableParserTest.cs
index 02fa41a..407a48e 100644
--- a/Maple2.File.Tests/ServerTableParserTest.cs
+++ b/Maple2.File.Tests/ServerTableParserTest.cs
@@ -144,6 +144,15 @@ public void TestShopGame() {
}
}
+ [TestMethod]
+ public void TestShopUgc() {
+ var parser = new ServerTableParser(TestUtils.ServerReader);
+
+ foreach ((_, _) in parser.ParseShopUgc()) {
+ continue;
+ }
+ }
+
[TestMethod]
public void TestShopBeauty() {
var parser = new ServerTableParser(TestUtils.ServerReader);
@@ -381,4 +390,13 @@ public void TestEnchantOption() {
continue;
}
}
+
+ [TestMethod]
+ public void TestMeretShop() {
+ var parser = new ServerTableParser(TestUtils.ServerReader);
+
+ foreach ((_, _) in parser.ParseShopMeret()) {
+ continue;
+ }
+ }
}