diff --git a/Maple2.File.Parser/BanWordParser.cs b/Maple2.File.Parser/BanWordParser.cs index d360c85..a149af2 100644 --- a/Maple2.File.Parser/BanWordParser.cs +++ b/Maple2.File.Parser/BanWordParser.cs @@ -16,27 +16,24 @@ public BanWordParser(M2dReader xmlReader) { nameSerializer = new XmlSerializer(typeof(StringMapping)); } + // banword.xml: the client refuses text that contains any of these. public IEnumerable<(int Id, string Name)> ParseBanWords() { - int i = 0; - foreach (PackFileEntry entry in xmlReader.Files.Where(entry => entry.Name.Contains("banword") && !entry.Name.Contains("ugc"))) { - XmlReader reader = xmlReader.GetXmlReader(entry); - var mapping = nameSerializer.Deserialize(reader) as StringMapping; - - Debug.Assert(mapping != null); + return Parse(name => name.Contains("banword") && !name.Contains("banwordall") && !name.Contains("ugc")); + } - Dictionary banWords = mapping.key.ToDictionary(_ => i++, key => key.name); - foreach (var banWord in banWords) { - if (string.IsNullOrEmpty(banWord.Value)) { - continue; - } - yield return (banWord.Key, banWord.Value); - } - } + // banwordall.xml: the client refuses these only as a whole space-delimited word, + // CBanTextChecker::FindBanWordAll in the KMS2 client, so they need their own list. + public IEnumerable<(int Id, string Name)> ParseBanWordAll() { + return Parse(name => name.Contains("banwordall")); } public IEnumerable<(int Id, string Name)> ParseUgcBanWords() { + return Parse(name => name.Contains("ugcbanword")); + } + + private IEnumerable<(int Id, string Name)> Parse(Func matchesFile) { int i = 0; - foreach (PackFileEntry entry in xmlReader.Files.Where(entry => entry.Name.Contains("ugcbanword"))) { + foreach (PackFileEntry entry in xmlReader.Files.Where(entry => matchesFile(entry.Name))) { XmlReader reader = xmlReader.GetXmlReader(entry); var mapping = nameSerializer.Deserialize(reader) as StringMapping; diff --git a/Maple2.File.Parser/Maple2.File.Parser.csproj b/Maple2.File.Parser/Maple2.File.Parser.csproj index 5917e98..0441abb 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.34 + 2.4.35 net8.0 README.md enable diff --git a/Maple2.File.Tests/BanWordParserTest.cs b/Maple2.File.Tests/BanWordParserTest.cs index c0aff33..1779e49 100644 --- a/Maple2.File.Tests/BanWordParserTest.cs +++ b/Maple2.File.Tests/BanWordParserTest.cs @@ -7,19 +7,27 @@ namespace Maple2.File.Tests; [TestClass] public class BanWordParserTest { + // Before banwordall.xml had its own method, ParseBanWords returned both files: 6179 words. [TestMethod] public void TestBanWordParser() { var locale = Locale.NA; Filter.Load(TestUtils.XmlReader, locale.ToString(), "Live"); var parser = new BanWordParser(TestUtils.XmlReader); - int count = 0; + var banWords = new List(); foreach ((int id, string name) in parser.ParseBanWords()) { Assert.IsTrue(id >= 0); Assert.IsFalse(string.IsNullOrEmpty(name)); - count++; + banWords.Add(name); } - Assert.AreEqual(6179, count); + var banWordAll = parser.ParseBanWordAll().Select(word => word.Name).ToList(); + + Assert.AreEqual(6179, banWords.Count + banWordAll.Count); + // en/banword.xml has "nazi"; "nig" is only ever in banwordall.xml. + CollectionAssert.Contains(banWords, "nazi"); + CollectionAssert.DoesNotContain(banWords, "nig"); + CollectionAssert.Contains(banWordAll, "nig"); + CollectionAssert.DoesNotContain(banWordAll, "nazi"); } [TestMethod]