Skip to content

Feat: KR Xml Parsing#49

Merged
AngeloTadeucci merged 6 commits intomasterfrom
dev
Apr 22, 2025
Merged

Feat: KR Xml Parsing#49
AngeloTadeucci merged 6 commits intomasterfrom
dev

Conversation

@AngeloTadeucci
Copy link
Collaborator

@AngeloTadeucci AngeloTadeucci commented Apr 20, 2025

Summary by CodeRabbit

  • New Features

    • Added comprehensive support for Korean (KR) locale data parsing across items, maps, NPCs, quests, skills, riding, scripts, tables, and more.
    • Introduced new data models and parsing logic for KR-specific XML structures, including job tables, item options, merge options, set items, and individual item drops.
    • Locale-aware file loading now enables seamless switching between NA and KR datasets.
    • Added new enum values and aliases to enhance data type coverage.
  • Bug Fixes

    • Improved XML serialization logic to handle empty arrays and null values more consistently.
    • Enhanced null safety for name lookups and XML data parsing.
  • Tests

    • Expanded test coverage for KR locale data, including new tests for KR item, map, NPC, quest, skill, riding, script, and table parsers.
    • Added assertions for expected data counts and improved test initialization for locale-specific scenarios.
    • Refactored tests to use shared parser instances and centralized setup.
  • Chores

    • Added a solution folder for environment configuration files and introduced a global.json for .NET SDK management.

@coderabbitai
Copy link

coderabbitai bot commented Apr 20, 2025

Walkthrough

This update introduces extensive support for Korean ("KR") locale data parsing across the codebase. It adds new XML-serializable classes, parsing methods, and test cases to handle KR-specific data structures for items, maps, NPCs, quests, skills, riding, scripts, tables, and item options. Many parsers now conditionally select data sources and deserialization types based on locale. Test coverage is expanded with new tests for KR data, including a comprehensive test suite for the TableParser with Korean datasets. Additional minor changes include enum updates, solution file adjustments, and the addition of a global.json for .NET SDK configuration.

Changes

Files/Groups Change Summary
Maple2.File.Generator/XmlArrayGenerator.cs Modified array serialization: null arrays now serialize as empty strings instead of null.
Maple2.File.Parser/Enum/*.cs (ConditionType, DungeonType, ItemExchangeScrollType, NameTagSymbolConditionType, QuestPropertyType, QuestRewardType) Added new enum members and aliases to support additional values and naming conventions.
Maple2.File.Parser/ItemOptionParser.cs, Maple2.File.Parser/Xml/Common/ItemOptionKR.cs, Maple2.File.Parser/Xml/ItemOptionConstant.cs, Maple2.File.Parser/Xml/ItemOptionRandom.cs, Maple2.File.Parser/Xml/Table/ItemMergeOption.cs Added KR-specific item option parsing, serializers, and XML classes for constants, random options, and merge options.
Maple2.File.Parser/ItemParser.cs, Maple2.File.Parser/Xml/Item/Item.cs Added KR-specific item data parsing and new XML classes for KR item structures. Updated parser to support locale-based deserialization.
Maple2.File.Parser/MapParser.cs, Maple2.File.Parser/Xml/Map/Map.cs Added KR-specific map data parsing and XML classes. Parser now selects data source and deserialization type by locale.
Maple2.File.Parser/NpcParser.cs, Maple2.File.Parser/Xml/Npc/Npc.cs Added KR-specific NPC data parsing and XML classes. Parser split into methods for NA and KR, with name parsing improvements.
Maple2.File.Parser/QuestParser.cs, Maple2.File.Parser/Xml/Quest/Quest.cs Refactored quest parsing to support KR data with separate XML classes and parsing methods. Added quest description parsing method.
Maple2.File.Parser/RidingParser.cs, Maple2.File.Parser/Xml/Riding/Riding.cs Added KR-specific riding data parsing and XML classes with support for passenger data.
Maple2.File.Parser/ScriptParser.cs, Maple2.File.Parser/Xml/Script/NpcScript.cs Added KR-specific NPC and quest script parsing and XML classes. Parser now supports single-file KR script parsing.
Maple2.File.Parser/SkillParser.cs, Maple2.File.Parser/Xml/Skill/Basic.cs, Maple2.File.Parser/Xml/Skill/Kinds.cs, Maple2.File.Parser/Xml/Skill/Skill.cs Added KR-specific skill data parsing and XML classes. Parser now modularized and supports both NA and KR skill structures.
Maple2.File.Parser/TableParser.cs, Maple2.File.Parser/Xml/Table/JobTable.cs, Maple2.File.Parser/Xml/Table/SetItemOption.cs, Maple2.File.Parser/Xml/Table/IndividualItemDrop.cs Enhanced table parsing for locale awareness, added KR-specific serializers and parsing methods for jobs, set items, and item drops.
Maple2.File.Parser/Tools/Sanitizer.cs Added method to remove UTF-8 BOM from XML strings.
Maple2.File.Parser/Xml/Item/Property.cs Changed moveDisable property type from int to bool.
Maple2.File.Parser/Xml/Table/DungeonRoom.cs Changed attribute on groupType from [XmlAttribute] to [M2dEnum].
Maple2.File.Tests/AdditionalEffectParserTest.cs, FunctionCubeParserTest.cs, ItemOptionParserTest.cs, ItemParserTest.cs, MapParserTest.cs, NifParserTest.cs, NpcParserTest.cs, QuestParserTest.cs, RidingParserTest.cs, ScriptParserTest.cs, SkillParserTest.cs, TableParserTest.cs, XBlockParserTest.cs Added or updated tests for KR data parsing, improved test initialization with filter loading, added count assertions, and introduced new test methods for locale-specific scenarios.
Maple2.File.Tests/TableParserKRTest.cs Added comprehensive new test class for KR-specific table parsing, covering a wide range of data types and structures.
Maple2.File.Tests/TestUtils.cs Removed default filter loading from static constructor. Added TestUtilsKr class for KR data sources and readers.
Maple2.File.sln Added "Solution Items" folder with .env and .env.example files.
global.json Added new file specifying .NET SDK version resolution and prerelease settings.

Sequence Diagram(s)

sequenceDiagram
    participant TestRunner
    participant Filter
    participant Parser (generic)
    participant KRParser
    participant DataSource (NA)
    participant DataSource (KR)
    participant XMLClass (NA)
    participant XMLClass (KR)

    TestRunner->>Filter: Load(region, environment)
    alt region == "KR"
        TestRunner->>KRParser: new KRParser(TestUtilsKr.XmlReader)
        KRParser->>DataSource (KR): Read KR XML data
        KRParser->>XMLClass (KR): Deserialize to KR-specific class
        KRParser-->>TestRunner: Yield parsed KR data
    else
        TestRunner->>Parser: new Parser(TestUtils.XmlReader)
        Parser->>DataSource (NA): Read NA XML data
        Parser->>XMLClass (NA): Deserialize to NA-specific class
        Parser-->>TestRunner: Yield parsed NA data
    end
Loading

Suggested reviewers

  • Zintixx

Poem

Hopping through code, from NA to KR,
A rabbit now parses both near and far!
With new classes and tests, the garden expands,
Locale-aware logic in all parser hands.
Tables and items, maps, quests galore—
This bunny ensures you can parse even more!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 19

🔭 Outside diff range comments (4)
Maple2.File.Tests/NifParserTest.cs (1)

33-110: ⚠️ Potential issue

ValidateNifMeshData exits silently when no mesh is found
Inside the per‑document loop, you continue when meshFound is false (lines 106‑108).
That means a document that should contain PhysX data could silently pass the test.
Fail fast instead—this is a unit test, not production code.

-if (!meshFound) {
-    continue;
-}
+Assert.IsTrue(meshFound, $"No PhysX mesh was found in {relpath}.");

This keeps accidental regressions from slipping through.

Maple2.File.Parser/SkillParser.cs (1)

53-66: ⚠️ Potential issue

Dictionary population can throw on duplicate Skill IDs

skillNames.Add(...) inside LoadSkillNames() will raise an exception if the same ID appears in multiple skillname files.

-for each (Key key in mapping.key) {
-    skillNames.Add(int.Parse(key.id), key.name);
-}
+foreach (Key key in mapping.key) {
+    skillNames[int.Parse(key.id)] = key.name; // last one wins
+}

This makes the parser resilient to duplicate definitions while keeping O(1) lookup.

Maple2.File.Parser/Xml/Table/JobTable.cs (1)

1-2: ⚠️ Potential issue

Missing using System / System.Collections.Generic

IList, List, Array, etc. are unresolved without these imports.

 using System.Xml.Serialization;
+using System;
+using System.Collections.Generic;
 using M2dXmlGenerator;
Maple2.File.Parser/Xml/Table/IndividualItemDrop.cs (1)

1-2: ⚠️ Potential issue

Core namespaces missing

Same as previous file; add:

 using System.Xml.Serialization;
+using System;
+using System.Collections.Generic;
 using M2dXmlGenerator;
🧹 Nitpick comments (24)
Maple2.File.Parser/Xml/Item/Property.cs (1)

45-45: Type change from int to bool improves semantics

The change from int to bool for the moveDisable property better represents its binary nature (either movement is disabled or not). This aligns with the PR's goal of refining XML schema adaptations for Korean locale support.

However, ensure this change is backward compatible with existing XML data. If any code was previously checking for specific integer values beyond 0/1, those areas may need updates.

Consider documenting this property with XML comments to clarify its purpose and behavior, especially since it's part of a locale-specific adaptation.

Maple2.File.Tests/TestUtils.cs (2)

54-68: Well-organized KR testing utilities.

The implementation of TestUtilsKR follows the same pattern as TestUtils, providing consistent access to Korean data files. The error message for missing environment variable is clear and helpful.

Consider extracting common code between TestUtils and TestUtilsKR to reduce duplication. A base class or shared utility method could be used to initialize readers with different root paths.

-public static class TestUtils {
+public abstract static class BaseTestUtils {
     public static readonly M2dReader XmlReader;
     public static readonly M2dReader ServerReader;
     // ... other shared fields
     
+    protected static void Initialize(string envVarName) {
+        DotEnv.Load();
+        string? m2dPath = Environment.GetEnvironmentVariable(envVarName);
+        if (string.IsNullOrEmpty(m2dPath)) {
+            throw new Exception($"{envVarName} is not set");
+        }
+        
+        // Initialize readers with m2dPath
+    }
}

+public static class TestUtils : BaseTestUtils {
+    static TestUtils() {
+        Initialize("MS2_DATA_FOLDER");
+    }
}

+public static class TestUtilsKR : BaseTestUtils {
+    static TestUtilsKR() {
+        Initialize("KMS2_DATA_FOLDER");
+    }
}

89-96: Duplicated debug handlers.

The debug handlers are identical to those in TestUtils, which reinforces the suggestion to extract common code.

The duplicate debug handlers could be moved to a shared utility class or the suggested base class to avoid repetition.

Maple2.File.Tests/XBlockParserTest.cs (1)

12-19: Consider keeping test methods active even if they're not regularly run

Instead of commenting out TestConversion, consider using the [Ignore] attribute as done with TestXBlockParserAll (line 55). This keeps the test in the codebase without running it, maintaining its visibility while documenting its purpose.

-    // [TestMethod]
-    // public void TestConversion() {
-    // var flatConverter = new FlatToModel(TestUtils.ExportedReader, TestUtils.AssetMetadataReader);
-    // flatConverter.Convert();
-
-    // var xblockConverter = new XBlockToBlock(TestUtils.ExportedReader);
-    // xblockConverter.Convert();
-    // }
+    [Ignore("Conversion test is slow and only needed occasionally")]
+    [TestMethod]
+    public void TestConversion() {
+        var flatConverter = new FlatToModel(TestUtils.ExportedReader, TestUtils.AssetMetadataReader);
+        flatConverter.Convert();
+
+        var xblockConverter = new XBlockToBlock(TestUtils.ExportedReader);
+        xblockConverter.Convert();
+    }
Maple2.File.Tests/FunctionCubeParserTest.cs (1)

27-39: Well-implemented KR-specific test

The new test method correctly tests the Korean locale version of the function cube parser, following the same pattern as the NA test and validating the expected count of 433 entries.

Consider adding the commented-out event handler subscriptions for unknown XML elements and attributes as in the NA test for consistency:

        var parser = new FunctionCubeParser(TestUtilsKR.XmlReader);

+        // parser.FunctionCubeSerializer.UnknownElement += TestUtils.UnknownElementHandler;
+        // parser.FunctionCubeSerializer.UnknownAttribute += TestUtils.UnknownAttributeHandler;

        int count = 0;
Maple2.File.Tests/TableParserTest.cs (1)

471-472: Remove redundant assignment.

The results are assigned to a variable but never used. The following line re-parses the same data.

-        var results = _parser.ParseAdventureLevelAbility();
-
         foreach ((_, _) in _parser.ParseAdventureLevelAbility()) {
Maple2.File.Parser/ItemParser.cs (1)

23-47: Generic Parse method to handle multiple item data structures.

The Parse<T>() method effectively handles both regular and Korean-specific item data structures through:

  1. Type parameter T constrained to class types
  2. Conditional folder path selection based on locale
  3. Type-specific processing in the switch statement

This is a clean approach that avoids code duplication while maintaining type safety.

However, the method could potentially throw an exception if an unexpected type is passed. Consider adding a default case to handle unexpected types:

switch (xml) {
    case ItemDataRoot root when root.environment != null:
        int itemId = int.Parse(Path.GetFileNameWithoutExtension(entry.Name));
        yield return (itemId, itemNames.GetValueOrDefault(itemId) ?? string.Empty, root.environment);
        break;
    case ItemDataKR rootKR:
        foreach (var dataRoot in rootKR.items) {
            if (dataRoot.environment == null) continue;
            yield return (dataRoot.id, itemNames.GetValueOrDefault(dataRoot.id) ?? string.Empty, dataRoot.environment);
        }
        break;
+   default:
+       Console.WriteLine($"Unexpected item data type: {typeof(T).Name}");
+       break;
}
Maple2.File.Tests/ItemOptionParserTest.cs (1)

99-106: Consider clarifying or removing commented-out test.

The commented-out TestItemOptionPickParserKR method with the note "Moved to constant" could be replaced with a clearer comment explaining where this functionality is now tested.

-// [TestMethod] // Moved to constant
-// public void TestItemOptionPickParserKR() {
-//     var parser = new ItemOptionParser(TestUtilsKR.XmlReader);
-//
-//     foreach (var data in parser.ParsePick()) {
-//         Assert.IsNotNull(data);
-//     }
-// }
+// Note: Option pick parsing for KR is now tested as part of the constant options in TestItemOptionParserKR
Maple2.File.Parser/Xml/ItemOptionRandom.cs (1)

1-7: Header comment references the wrong source file
The comment says itemoptionconstant.xml but this model maps itemoptionrandom.xml.
This will confuse maintainers searching for the mapping.

-// ./data/xml/table/itemoptionconstant.xml
+// ./data/xml/table/itemoptionrandom.xml
Maple2.File.Parser/MapParser.cs (3)

21-23: Hard‑coded English map‑name file breaks KR localisation
Even in KR mode the parser still loads en/mapname.xml (line 26).
If a KR‑specific map‑name file exists the names will be wrong or missing.

-XmlReader reader = xmlReader.GetXmlReader(xmlReader.GetEntry("en/mapname.xml"));
+string nameFile = FeatureLocaleFilter.Locale == "KR" ? "kr/mapname.xml" : "en/mapname.xml";
+XmlReader reader = xmlReader.GetXmlReader(xmlReader.GetEntry(nameFile));

Please confirm the correct path and encoding of the KR map‑name file.


32-38: Repeated LINQ allocation can be avoided
xmlReader.Files.Where(entry => entry.Name.StartsWith("map/"));
creates an intermediate collection on every call to Parse().
Files is already enumerable; switching to an iterator (foreach) or embedding the predicate in the loop eliminates the extra allocation.


59-60: Use TryGetValue to avoid double dictionary lookup
mapNames.GetValueOrDefault(mapId) ?? string.Empty performs two look‑ups when the key is present.

-mapNames.GetValueOrDefault(mapId) ?? string.Empty
-mapNames.TryGetValue(mapId, out var name) ? name : string.Empty

Minor, but free performance win when parsing thousands of maps.

Maple2.File.Parser/Xml/Table/ItemMergeOption.cs (1)

89-103: Comprehensive OptionKR class with max value attributes.

Instead of arrays, the KR option uses direct max value attributes for each index. This is a good representation of the KR XML structure. Consider adding an indexer similar to the original Option class to make accessing values by index consistent across implementations.

public partial class OptionKR {
    [XmlAttribute] public string optionName = string.Empty;
    [XmlAttribute] public int min;

    [XmlAttribute] public float idx0_max;
    [XmlAttribute] public float idx1_max;
    [XmlAttribute] public float idx2_max;
    [XmlAttribute] public float idx3_max;
    [XmlAttribute] public float idx4_max;
    [XmlAttribute] public float idx5_max;
    [XmlAttribute] public float idx6_max;
    [XmlAttribute] public float idx7_max;
    [XmlAttribute] public float idx8_max;
    [XmlAttribute] public float idx9_max;
+    
+    public float GetMaxAt(int i) => i switch {
+        0 => idx0_max,
+        1 => idx1_max,
+        2 => idx2_max,
+        3 => idx3_max,
+        4 => idx4_max,
+        5 => idx5_max,
+        6 => idx6_max,
+        7 => idx7_max,
+        8 => idx8_max,
+        9 => idx9_max,
+        _ => throw new ArgumentOutOfRangeException(nameof(i), i, "Invalid option index."),
+    };
}
Maple2.File.Parser/NpcParser.cs (1)

32-45: Minor: repeated ParseNpcNames() call per parser instance

Parse() and ParseKR() each rebuild the same dictionary.
Caching the result in a private, lazily‑initialised field would avoid redundant XML reads when both methods are invoked.

Maple2.File.Tests/QuestParserTest.cs (2)

20-28: Hard‑coded expected counts make the test brittle

The assertions Assert.AreEqual(4903, count) and similar lock the test suite to a specific data‑set version.
A minor data file update will fail the build even if the parser logic is correct.

Recommended alternatives:
• Assert that count is > 0 and maybe within a broad range, or
• Load an expected count from a manifest shipped alongside the XML so tests evolve with the data.


30-48: Duplicate code across NA/KR tests

The four test methods share identical setup & counting logic. Extract the common loop into a private helper and parameterise by locale and expected count to improve maintainability.

Maple2.File.Parser/QuestParser.cs (1)

57-75: Hard‑coded "string/en" path ignores active locale

ParseQuestDescriptions() always reads English description files. For KR builds this yields English names (or none if the files are absent).

Consider resolving the folder dynamically:

string langFolder = FeatureLocaleFilter.Locale == "KR" ? "string/kr" : "string/en";
foreach (PackFileEntry entry in xmlReader.Files.Where(e => e.Name.StartsWith($"{langFolder}/questdescription"))) { ... }
Maple2.File.Parser/Xml/Table/IndividualItemDrop.cs (1)

85-98: Consider aligning field naming with existing model

Existing (non‑KR) model uses item, item2, weight, etc.
The KR model switches to itemID, itemID2, uiItemRank, etc. If you intend consumers to handle the two variants generically, you may want to:

  1. Keep identical property names where semantics match, or
  2. Introduce an interface / base class so callers don’t need if (locale…) cascades.

Not blocking, but think about long‑term maintainability.

Maple2.File.Parser/Xml/Skill/Kinds.cs (1)

38-68: Reduce duplication between Kinds and KindsKR.

KindsKR re‑lists ~30 identical fields from Kinds, differing only in immediateActive’s type (boolint).
Long‑term this will be a maintenance liability: any future field added to Kinds must be manually copied to KindsKR.

Consider extracting the common data into a base record/struct, or re‑using Kinds via composition/inheritance and exposing only the truly divergent members:

-public partial class KindsKR {
-    // … 30 duplicated members …
-    [XmlAttribute] public int immediateActive; // 0,1,2
-}
+public partial class KindsKR : Kinds {
+    // override the single divergent field
+    [XmlAttribute] public new int immediateActive; // 0,1,2
+}

That keeps the serializers intact while eliminating the copy‑paste burden.

Maple2.File.Parser/Xml/Item/Item.cs (1)

55-85: Duplicate property lists hurt maintainability.

ItemDataKR repeats the full 40‑property list from ItemData. Future edits will require touching both classes.

If the schema is truly identical, prefer:

public partial class ItemDataKR : ItemData { /* KR‑only overrides here */ }

or share a common interface/record generated from the XSD.

Maple2.File.Parser/Xml/Common/ItemOptionKR.cs (1)

40-75: Large switch blocks → data‑driven table

StatValue(byte i) contains 30 case labels that map indices to backing fields.
The same pattern is repeated for the other three getters, totalling >250 case labels.

For readability & JIT friendliness you could replace the switches with static arrays:

-private int StatValue(byte i) => i switch { 0 => str_value_base, … };
+private static readonly Func<ItemOptionKR, int>[] _statValue =
+{
+    o => o.str_value_base,
+    o => o.dex_value_base,
+    // …
+};
+public int StatValue(byte i) =>
+    i < _statValue.Length ? _statValue[i](this)
+                          : throw new ArgumentOutOfRangeException(nameof(i), i, null);

Benefits:
• far smaller IL,
• easier to audit,
• constant‑time amendments (just reorder the array).

Same approach applies to StatRate, SpecialValue, and SpecialRate.

Maple2.File.Parser/TableParser.cs (2)

236-242: Path selection pattern repeats – extract helper.

Several methods now follow the “locale == "kr" ? koreanPath : naPath” pattern.
Centralising this into a small helper keeps the parser concise:

private string L(string na, string kr) => locale == "kr" ? kr : na;

// usage
string filename = L("table/na/colorpalette_achieve.xml", "table/colorpalette.xml");

This removes ~40 if blocks across the file.


802-818: Minor: consider eager grouping to avoid repeat enumerations.

ParseIndividualItemDropKR() performs two GroupBy passes (GroupBy then SelectMany).
Materialising dropBox.Groups into a dictionary once per drop box can cut allocations:

yield return (dropBox.DropBoxID,
-    dropBox.Groups.GroupBy(g => (byte)g.DropGroupID)
-        .ToDictionary(g => g.Key, g => g.SelectMany(grp => grp.Items).ToList()));
+    dropBox.Groups
+        .GroupBy(g => (byte)g.DropGroupID, g => g.Items)
+        .ToDictionary(g => g.Key, g => g.SelectMany(i => i).ToList()));
Maple2.File.Tests/TableParserKRTest.cs (1)

444-451: Remove redundant API call

The method calls ParseAdventureLevelAbility() twice, with the first result stored in an unused variable results. This redundancy is unnecessary and could affect test performance.

Apply this diff to remove the redundant call:

[TestMethod]
public void TestAdventureLevelAbilityKR() {
-    var results = _parser.ParseAdventureLevelAbility();

    foreach ((_, _) in _parser.ParseAdventureLevelAbility()) {
        continue;
    }
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74361ba and d0d4ca6.

📒 Files selected for processing (54)
  • Maple2.File.Generator/XmlArrayGenerator.cs (1 hunks)
  • Maple2.File.Parser/Enum/ConditionType.cs (1 hunks)
  • Maple2.File.Parser/Enum/DungeonType.cs (1 hunks)
  • Maple2.File.Parser/Enum/ItemExchangeScrollType.cs (1 hunks)
  • Maple2.File.Parser/Enum/NameTagSymbolConditionType.cs (1 hunks)
  • Maple2.File.Parser/Enum/QuestPropertyType.cs (1 hunks)
  • Maple2.File.Parser/Enum/QuestRewardType.cs (1 hunks)
  • Maple2.File.Parser/ItemOptionParser.cs (5 hunks)
  • Maple2.File.Parser/ItemParser.cs (2 hunks)
  • Maple2.File.Parser/MapParser.cs (3 hunks)
  • Maple2.File.Parser/NpcParser.cs (2 hunks)
  • Maple2.File.Parser/QuestParser.cs (3 hunks)
  • Maple2.File.Parser/RidingParser.cs (2 hunks)
  • Maple2.File.Parser/ScriptParser.cs (4 hunks)
  • Maple2.File.Parser/SkillParser.cs (2 hunks)
  • Maple2.File.Parser/TableParser.cs (34 hunks)
  • Maple2.File.Parser/Tools/Sanitizer.cs (1 hunks)
  • Maple2.File.Parser/Xml/Common/ItemOptionKR.cs (1 hunks)
  • Maple2.File.Parser/Xml/Item/Item.cs (1 hunks)
  • Maple2.File.Parser/Xml/Item/Property.cs (1 hunks)
  • Maple2.File.Parser/Xml/ItemOptionConstant.cs (1 hunks)
  • Maple2.File.Parser/Xml/ItemOptionRandom.cs (1 hunks)
  • Maple2.File.Parser/Xml/Map/Map.cs (1 hunks)
  • Maple2.File.Parser/Xml/Npc/Npc.cs (1 hunks)
  • Maple2.File.Parser/Xml/Quest/Quest.cs (1 hunks)
  • Maple2.File.Parser/Xml/Riding/Riding.cs (1 hunks)
  • Maple2.File.Parser/Xml/Script/NpcScript.cs (1 hunks)
  • Maple2.File.Parser/Xml/Skill/Basic.cs (1 hunks)
  • Maple2.File.Parser/Xml/Skill/Kinds.cs (1 hunks)
  • Maple2.File.Parser/Xml/Skill/Skill.cs (2 hunks)
  • Maple2.File.Parser/Xml/Table/DungeonRoom.cs (1 hunks)
  • Maple2.File.Parser/Xml/Table/IndividualItemDrop.cs (1 hunks)
  • Maple2.File.Parser/Xml/Table/ItemMergeOption.cs (1 hunks)
  • Maple2.File.Parser/Xml/Table/JobTable.cs (1 hunks)
  • Maple2.File.Parser/Xml/Table/SetItemOption.cs (1 hunks)
  • Maple2.File.Tests/AdditionalEffectParserTest.cs (3 hunks)
  • Maple2.File.Tests/AiParserTest.cs (1 hunks)
  • Maple2.File.Tests/FunctionCubeParserTest.cs (2 hunks)
  • Maple2.File.Tests/ItemOptionParserTest.cs (6 hunks)
  • Maple2.File.Tests/ItemParserTest.cs (2 hunks)
  • Maple2.File.Tests/MapParserTest.cs (2 hunks)
  • Maple2.File.Tests/NifParserTest.cs (2 hunks)
  • Maple2.File.Tests/NpcParserTest.cs (2 hunks)
  • Maple2.File.Tests/QuestParserTest.cs (2 hunks)
  • Maple2.File.Tests/RidingParserTest.cs (4 hunks)
  • Maple2.File.Tests/ScriptParserTest.cs (5 hunks)
  • Maple2.File.Tests/ServerTableParserTest.cs (1 hunks)
  • Maple2.File.Tests/SkillParserTest.cs (3 hunks)
  • Maple2.File.Tests/TableParserKRTest.cs (1 hunks)
  • Maple2.File.Tests/TableParserTest.cs (2 hunks)
  • Maple2.File.Tests/TestUtils.cs (1 hunks)
  • Maple2.File.Tests/XBlockParserTest.cs (3 hunks)
  • Maple2.File.sln (1 hunks)
  • global.json (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
Maple2.File.Tests/ItemOptionParserTest.cs (1)
Learnt from: AngeloTadeucci
PR: AngeloTadeucci/Maple2.File#36
File: Maple2.File.Tests/TableParserTest.cs:777-783
Timestamp: 2024-10-09T04:13:28.776Z
Learning: In the 'Maple2.File' project, tests are designed to ensure methods can be called without errors; do not suggest adding assertions or validations in test methods.
🧬 Code Graph Analysis (17)
Maple2.File.Parser/Xml/Script/NpcScript.cs (2)
Maple2.File.Parser/Xml/Npc/Npc.cs (2)
  • XmlRoot (7-11)
  • XmlRoot (42-45)
Maple2.File.Parser/Xml/Script/QuestScript.cs (1)
  • XmlRoot (7-10)
Maple2.File.Tests/SkillParserTest.cs (4)
Maple2.File.Parser/Tools/Filter.cs (1)
  • Filter (9-47)
Maple2.File.Tests/TestUtils.cs (4)
  • TestUtils (11-52)
  • TestUtils (19-43)
  • TestUtilsKR (55-96)
  • TestUtilsKR (63-87)
Maple2.File.Parser/SkillParser.cs (3)
  • SkillParser (12-67)
  • SkillParser (17-22)
  • Dictionary (53-66)
Maple2.File.Parser/Xml/Skill/Skill.cs (1)
  • SkillKR (148-163)
Maple2.File.Parser/RidingParser.cs (3)
Maple2.File.Parser/Xml/Riding/Riding.cs (1)
  • RidingKR (28-30)
Maple2.File.IO/M2dReader.cs (1)
  • GetString (64-67)
Maple2.File.Parser/Tools/Sanitizer.cs (2)
  • Sanitizer (5-105)
  • RemoveEmpty (85-87)
Maple2.File.Parser/ItemOptionParser.cs (5)
Maple2.File.Parser/Xml/ItemOptionConstant.cs (1)
  • ItemOptionConstant (35-39)
Maple2.File.Parser/Tools/Sanitizer.cs (3)
  • Sanitizer (5-105)
  • RemoveEmpty (85-87)
  • RemoveUtf8Bom (99-104)
Maple2.File.IO/M2dReader.cs (2)
  • GetString (64-67)
  • XmlReader (43-45)
Maple2.File.Parser/Xml/ItemOptionRandom.cs (1)
  • ItemOptionRandomKR (9-18)
Maple2.File.Parser/Xml/Table/ItemMergeOption.cs (1)
  • MergeOptionKR (76-80)
Maple2.File.Parser/Xml/Quest/Quest.cs (4)
Maple2.File.Parser/Xml/Item/Item.cs (2)
  • XmlRoot (7-10)
  • XmlRoot (45-48)
Maple2.File.Parser/Xml/Npc/Npc.cs (2)
  • XmlRoot (7-11)
  • XmlRoot (42-45)
Maple2.File.Parser/Xml/Skill/Skill.cs (2)
  • XmlRoot (10-14)
  • XmlRoot (142-146)
Maple2.File.Parser/Xml/Script/QuestScript.cs (1)
  • XmlRoot (7-10)
Maple2.File.Parser/Xml/Table/ItemMergeOption.cs (1)
Maple2.File.Parser/Xml/Table/ItemOptionVariation.cs (2)
  • XmlRoot (7-20)
  • XmlRoot (23-70)
Maple2.File.Tests/XBlockParserTest.cs (2)
Maple2.File.Tests/TestUtils.cs (2)
  • TestUtilsKR (55-96)
  • TestUtilsKR (63-87)
Maple2.File.Parser/MapXBlock/XBlockParser.cs (4)
  • XBlockParser (10-174)
  • XBlockParser (20-27)
  • ParseMap (59-67)
  • IMapEntity (120-163)
Maple2.File.Tests/FunctionCubeParserTest.cs (3)
Maple2.File.Parser/Tools/Filter.cs (1)
  • Filter (9-47)
Maple2.File.Tests/TestUtils.cs (4)
  • TestUtils (11-52)
  • TestUtils (19-43)
  • TestUtilsKR (55-96)
  • TestUtilsKR (63-87)
Maple2.File.Parser/FunctionCubeParser.cs (2)
  • FunctionCubeParser (11-33)
  • FunctionCubeParser (15-18)
Maple2.File.Parser/QuestParser.cs (8)
Maple2.File.Generator/Resource/FeatureLocaleFilter.cs (1)
  • FeatureLocaleFilter (7-76)
Maple2.File.Parser/ItemParser.cs (1)
  • IEnumerable (23-48)
Maple2.File.Parser/MapParser.cs (1)
  • IEnumerable (25-61)
Maple2.File.Parser/NpcParser.cs (3)
  • IEnumerable (32-45)
  • IEnumerable (47-61)
  • Dictionary (25-30)
Maple2.File.Parser/AchieveParser.cs (1)
  • IEnumerable (23-41)
Maple2.File.Parser/Xml/Quest/Quest.cs (2)
  • QuestData (17-54)
  • QuestDataKR (62-64)
Maple2.File.IO/M2dReader.cs (3)
  • PackFileEntry (39-41)
  • XmlReader (43-45)
  • GetString (64-67)
Maple2.File.Parser/Tools/Sanitizer.cs (2)
  • Sanitizer (5-105)
  • SanitizeQuest (61-65)
Maple2.File.Parser/Xml/Npc/Npc.cs (3)
Maple2.File.Parser/Xml/Item/Item.cs (2)
  • XmlRoot (7-10)
  • XmlRoot (45-48)
Maple2.File.Parser/Xml/Script/NpcScript.cs (2)
  • XmlRoot (7-13)
  • XmlRoot (15-18)
Maple2.File.Parser/Xml/Npc/Dummy.cs (1)
  • EffectDummy (7-9)
Maple2.File.Parser/Xml/ItemOptionRandom.cs (8)
Maple2.File.Parser/Xml/Item/Item.cs (2)
  • XmlRoot (7-10)
  • XmlRoot (45-48)
Maple2.File.Parser/Xml/Map/Map.cs (2)
  • XmlRoot (7-10)
  • XmlRoot (31-35)
Maple2.File.Parser/Xml/ItemOptionConstant.cs (2)
  • XmlRoot (8-11)
  • XmlRoot (30-33)
Maple2.File.Parser/Xml/Riding/Riding.cs (2)
  • XmlRoot (8-11)
  • XmlRoot (23-26)
Maple2.File.Parser/Xml/Quest/Quest.cs (2)
  • XmlRoot (8-11)
  • XmlRoot (57-60)
Maple2.File.Parser/Xml/Script/NpcScript.cs (2)
  • XmlRoot (7-13)
  • XmlRoot (15-18)
Maple2.File.Parser/Xml/Npc/Npc.cs (2)
  • XmlRoot (7-11)
  • XmlRoot (42-45)
Maple2.File.Parser/Xml/Table/ItemMergeOption.cs (1)
  • XmlRoot (8-11)
Maple2.File.Parser/Xml/Table/SetItemOption.cs (2)
Maple2.File.Parser/Xml/ItemOptionRandom.cs (1)
  • XmlRoot (4-7)
Maple2.File.Parser/Xml/Table/SetItemInfo.cs (1)
  • XmlRoot (7-10)
Maple2.File.Parser/Xml/Table/IndividualItemDrop.cs (6)
Maple2.File.Parser/Xml/ItemOptionRandom.cs (1)
  • XmlRoot (4-7)
Maple2.File.Parser/Xml/Map/Map.cs (2)
  • XmlRoot (7-10)
  • XmlRoot (31-35)
Maple2.File.Parser/Xml/ItemOptionConstant.cs (2)
  • XmlRoot (8-11)
  • XmlRoot (30-33)
Maple2.File.Parser/Xml/Quest/Quest.cs (2)
  • XmlRoot (8-11)
  • XmlRoot (57-60)
Maple2.File.Parser/Xml/Script/NpcScript.cs (2)
  • XmlRoot (7-13)
  • XmlRoot (15-18)
Maple2.File.Parser/Xml/Npc/Npc.cs (2)
  • XmlRoot (7-11)
  • XmlRoot (42-45)
Maple2.File.Tests/NpcParserTest.cs (4)
Maple2.File.Parser/Tools/Filter.cs (2)
  • Filter (9-47)
  • Load (12-46)
Maple2.File.Tests/TestUtils.cs (4)
  • TestUtils (11-52)
  • TestUtils (19-43)
  • TestUtilsKR (55-96)
  • TestUtilsKR (63-87)
Maple2.File.Parser/NpcParser.cs (2)
  • NpcParser (13-62)
  • NpcParser (18-23)
Maple2.File.Parser/Xml/Npc/Dummy.cs (1)
  • EffectDummy (7-9)
Maple2.File.Parser/Xml/Riding/Riding.cs (10)
Maple2.File.Parser/Xml/Item/Item.cs (2)
  • XmlRoot (7-10)
  • XmlRoot (45-48)
Maple2.File.Parser/Xml/ItemOptionRandom.cs (1)
  • XmlRoot (4-7)
Maple2.File.Parser/Xml/Map/Map.cs (2)
  • XmlRoot (7-10)
  • XmlRoot (31-35)
Maple2.File.Parser/Xml/ItemOptionConstant.cs (2)
  • XmlRoot (8-11)
  • XmlRoot (30-33)
Maple2.File.Parser/Xml/Quest/Quest.cs (2)
  • XmlRoot (8-11)
  • XmlRoot (57-60)
Maple2.File.Parser/Xml/Script/NpcScript.cs (2)
  • XmlRoot (7-13)
  • XmlRoot (15-18)
Maple2.File.Parser/Xml/Npc/Npc.cs (1)
  • XmlRoot (7-11)
Maple2.File.Parser/Xml/Riding/PassengerRiding.cs (2)
  • XmlRoot (8-11)
  • PassengerRiding (13-30)
Maple2.File.Parser/Xml/Table/MapSpawnTag.cs (1)
  • XmlRoot (7-22)
Maple2.File.Parser/Xml/Table/PetSpawnInfo.cs (1)
  • XmlRoot (6-9)
Maple2.File.Parser/SkillParser.cs (7)
Maple2.File.Generator/Resource/FeatureLocaleFilter.cs (1)
  • FeatureLocaleFilter (7-76)
Maple2.File.Parser/ItemParser.cs (1)
  • IEnumerable (23-48)
Maple2.File.Parser/MapParser.cs (1)
  • IEnumerable (25-61)
Maple2.File.Parser/NpcParser.cs (3)
  • IEnumerable (32-45)
  • IEnumerable (47-61)
  • Dictionary (25-30)
Maple2.File.Parser/AdditionalEffectParser.cs (1)
  • IEnumerable (18-29)
Maple2.File.IO/M2dReader.cs (1)
  • PackFileEntry (39-41)
Maple2.File.Parser/Xml/Skill/Skill.cs (1)
  • SkillKR (148-163)
Maple2.File.Parser/Xml/Table/JobTable.cs (13)
Maple2.File.Parser/Xml/Script/NpcScript.cs (2)
  • XmlRoot (7-13)
  • XmlRoot (15-18)
Maple2.File.Parser/Xml/Skill/Skill.cs (2)
  • XmlRoot (10-14)
  • XmlRoot (142-146)
Maple2.File.Parser/Xml/Table/DefaultItems.cs (1)
  • XmlRoot (7-30)
Maple2.File.Parser/Xml/Script/QuestScript.cs (1)
  • XmlRoot (7-10)
Maple2.File.Parser/Xml/Table/EnchantScroll.cs (1)
  • XmlRoot (7-10)
Maple2.File.Parser/Xml/Table/Fish.cs (1)
  • XmlRoot (7-10)
Maple2.File.Parser/Xml/Table/FishingSpot.cs (1)
  • XmlRoot (7-10)
Maple2.File.Parser/Xml/Table/GuildNpc.cs (1)
  • XmlRoot (8-11)
Maple2.File.Parser/Xml/Table/GuildProperty.cs (1)
  • XmlRoot (7-10)
Maple2.File.Parser/Xml/Table/ItemSocket.cs (1)
  • XmlRoot (7-10)
Maple2.File.Parser/Xml/Table/ItemSocketScroll.cs (1)
  • XmlRoot (7-10)
Maple2.File.Parser/Xml/Table/Feature.cs (1)
  • XmlRoot (6-9)
Maple2.File.Parser/Xml/Table/FeatureSetting.cs (1)
  • XmlRoot (6-9)
🔇 Additional comments (76)
Maple2.File.Tests/AiParserTest.cs (1)

124-124: Approve formatting adjustment
The addition of a trailing newline at the end of the file is a harmless formatting improvement that aligns with POSIX text file conventions.

global.json (1)

1-6: LGTM: SDK configuration ensures development environment consistency

This global.json configuration ensures all developers use consistent .NET SDK versions by rolling forward to the latest major version and allowing prereleases when needed.

Maple2.File.Parser/Enum/DungeonType.cs (1)

42-42: LGTM: Appropriate alias for locale support

The kill alias for the Kill enum value provides case-insensitive compatibility for XML deserialization, which is useful for supporting different locale formats.

Maple2.File.Parser/Xml/Skill/Basic.cs (1)

12-16: LGTM: Well-structured Korean locale support class

The BasicKR class correctly implements the IFeatureLocale interface and follows the same structure as the original Basic class while using the appropriate KindsKR type for Korean locale support.

Maple2.File.Parser/Tools/Sanitizer.cs (1)

99-104: LGTM: Useful UTF-8 BOM removal utility

This method effectively removes the UTF-8 BOM character from the beginning of XML strings, which is important for proper parsing of files from different sources, especially Korean locale files that may include this marker.

Maple2.File.sln (1)

16-21: Solution structure update looks good.

Added a "Solution Items" folder with environment files that will help manage locale-specific configurations. This addition aligns well with the KR XML parsing feature being implemented.

Maple2.File.Parser/Xml/Map/Map.cs (2)

30-35: Clear documentation of XML structure.

The comment clearly identifies the XML file path for KR data format. The class structure appropriately reflects the different XML organization compared to the non-KR format.


37-40: Well-structured KR-specific mapping.

The partial class implementation with ID attribute and feature locale annotation follows the same pattern used in the non-KR version, which provides consistency in the codebase.

Maple2.File.Tests/TestUtils.cs (1)

69-87: Identical M2dReader initialization pattern.

The file paths and reader initialization for KR data follows the same pattern as the non-KR version, maintaining consistency.

Maple2.File.Parser/Xml/Table/SetItemOption.cs (3)

31-35: Clear XML path documentation and appropriate root class.

The comment specifies the XML file path, and the root class structure with [XmlRoot("ms2")] follows the same pattern as other XML serialization classes. The option list using the "set" XML element correctly models the KR-specific format.


37-42: Well-defined KR item option structure.

The SetItemOptionKR class properly implements IFeatureLocale and includes the necessary attributes for the Korean format. The itemIDs array initialization with = [] ensures it's never null.


44-54: Consistent implementation of nested Part class.

The nested Part class appropriately inherits from ItemOptionKR (instead of ItemOption) to match the Korean data format. All attributes mirror the non-KR version, maintaining consistency between the implementations.

Maple2.File.Tests/ServerTableParserTest.cs (1)

439-439: Skip: Trailing newline addition
No functional changes; only a trailing newline was added.

Maple2.File.Parser/Enum/QuestPropertyType.cs (1)

7-7: New enum member added: hideworldmap
The addition of hideworldmap = 3 follows the existing value sequence and naming style. Please verify that the quest parser and its tests have been updated to handle this new property.

Maple2.File.Parser/Enum/ItemExchangeScrollType.cs (1)

8-8: New enum member added: upgrade
Adding upgrade = 4 is consistent with other scroll types. Ensure that any parsing logic or switch statements are updated accordingly and covered by tests.

Maple2.File.Parser/Enum/NameTagSymbolConditionType.cs (1)

16-16: New enum member added: return_user
The new return_user entry aligns with the overall enum updates. Confirm that any consumers of NameTagSymbolConditionType (parsers, serializers, UI mappings) have been extended and tested.

Maple2.File.Parser/Enum/QuestRewardType.cs (1)

7-7: LGTM - Added capitalized alias for consistent enum handling

The addition of SkillPoint as an alias for skillPoint (sharing the same value 2) seems to be part of supporting Korean locale data parsing where the capitalization might differ in the XML.

Maple2.File.Parser/Xml/Table/DungeonRoom.cs (1)

18-18: Attribute changed from [XmlAttribute] to [M2dEnum] for improved enum handling

The change from [XmlAttribute] to [M2dEnum] for the groupType property allows for more specialized handling of enum serialization/deserialization, which is consistent with the broader KR XML parsing enhancements in this PR.

Maple2.File.Generator/XmlArrayGenerator.cs (1)

69-69: Improved handling of null arrays in XML serialization

Changed from returning null to returning string.Empty when serializing null array fields. This prevents potential XML serialization issues and ensures more consistent behavior across different locales.

Maple2.File.Tests/XBlockParserTest.cs (1)

38-53: LGTM - Added KR version of XBlock parser test

The new test method TestXBlockParserKR correctly uses the Korean data sources through TestUtilsKR.ExportedReader, maintaining parity with the existing TestXBlockParser method. This addition properly validates that XBlock parsing works for Korean map data.

Maple2.File.Parser/Xml/Script/NpcScript.cs (1)

15-22: Good implementation of KR-specific classes for NPC scripts

The implementation correctly follows the pattern established across the codebase for Korean locale support. The NpcScriptListKR serves as the root container for multiple NPC scripts in the consolidated KR format, while NpcScriptKR extends the base NpcScript class to add the necessary id attribute for identification within the consolidated file.

Maple2.File.Parser/Xml/Riding/Riding.cs (1)

22-30: Well-structured implementation for Korean riding data

The implementation correctly extends the riding model to support the Korean format which includes passenger information. The inheritance hierarchy is appropriate - RidingKR extends Riding to inherit all base properties while adding the KR-specific passengers list. The XML structure is properly defined with appropriate root and element annotations.

Maple2.File.Parser/Xml/Quest/Quest.cs (1)

57-64: Good implementation of KR-specific quest data classes

The implementation correctly follows the pattern established across the codebase for Korean locale support. The QuestDataRootKR serves as the root container for multiple quests in the consolidated KR format, while QuestDataKR extends the base QuestData class to add the necessary id attribute for identification. The implementation of IFeatureLocale interface in QuestDataKR is appropriate for locale-specific filtering.

Maple2.File.Tests/FunctionCubeParserTest.cs (1)

12-25: Good addition of locale filter and validation

The changes to the existing test method correctly add locale filtering initialization and validate the expected count of function cube entries, which improves the test's thoroughness and consistency with other test methods in the codebase.

Maple2.File.Tests/AdditionalEffectParserTest.cs (2)

12-12: LGTM! Proper filter loading added before parser creation.

Great addition of the filter loading for North American region, ensuring the parser operates with the correct locale context.


24-36: Well-structured test for KR locale data parsing.

This test method follows the appropriate pattern for testing locale-specific functionality. It correctly:

  1. Loads the KR filter
  2. Uses the Korean XML reader
  3. Applies the same validation as the NA version
  4. Verifies the expected count (6070) of parsed items

The test ensures the AdditionalEffectParser correctly handles Korean locale data.

Maple2.File.Tests/TableParserTest.cs (1)

10-16: Good refactoring to static parser instance.

Excellent change to use a single static TableParser instance initialized once per test class. This optimization:

  1. Reduces redundancy by avoiding parser recreation for each test method
  2. Improves test efficiency
  3. Ensures consistent filter configuration across all tests
Maple2.File.Tests/RidingParserTest.cs (2)

12-12: LGTM! Filter loading properly added.

Good addition of Filter.Load calls before parser creation, ensuring correct locale context for both test methods.

Also applies to: 27-28


40-58: Comprehensive KR riding test with proper passenger validation.

Well-structured test that:

  1. Correctly loads the KR filter and uses the Korean XML reader
  2. Tests the new ParseKR() method
  3. Includes thorough validation for passenger objects
  4. Verifies the expected count of 615 riding entries

The additional validation for passengers is particularly good - it ensures that complex nested data structures are properly parsed.

Maple2.File.Tests/MapParserTest.cs (2)

12-12: LGTM! Added filter loading and count verification.

Good additions including:

  1. Filter loading with proper region parameters
  2. Counting parsed maps
  3. Asserting the exact expected count (1200)

These changes ensure the parser operates with the correct locale context and validates the expected dataset size.

Also applies to: 20-27


30-47: Well-structured test for KR map data.

This test method follows the appropriate pattern for testing locale-specific functionality:

  1. Loads the KR filter
  2. Uses the Korean XML reader
  3. Applies thorough validation including ID and nullability checks
  4. Verifies that exactly 1299 maps are parsed from the Korean dataset

The commented-out event handlers maintain consistency with the NA test method.

Maple2.File.Parser/RidingParser.cs (2)

15-15: Field added to support Korean locale parsing.

The ridingKRSerializer field is added to deserialize the Korean-specific riding data structure.


21-21: Constructor initialized with Korean-specific serializer.

The serializer is correctly initialized with the RidingKRRoot type, consistent with the pattern used for other serializers.

Maple2.File.Parser/Xml/Npc/Npc.cs (3)

42-45: Added Korean-specific NPC data list class.

The NpcDataListKR class is correctly defined with the "ms2" XML root and contains a list of NpcDataRootKR objects. This follows the same pattern used for other Korean-specific data structures.


47-50: Added Korean-specific NPC data root class.

The NpcDataRootKR class properly defines the structure for individual NPC entries with an ID attribute and environment element. This matches the expected XML structure for Korean NPC data.


52-54:

Details

❌ Incorrect review comment

Potential duplication of effectdummy property.

The NpcDataKR class adds an effectdummy property, but the regular NpcDataRoot class already has this property (line 10). This suggests a potential structural inconsistency between the regular and Korean XML formats.


🏁 Script executed:

#!/bin/bash
# Check both data structures to understand the difference in effectdummy placement
echo "Checking NpcDataRoot effectdummy usage:"
rg -A 3 -B 3 "effectdummy" --glob "*.cs"

Length of output: 2421


Ignore the reported duplication of effectdummy.

The two effectdummy properties live in separate XML contexts by design:

  • NpcDataRoot.effectdummy maps the <effectdummy> element at the root level for the default format.
  • NpcDataKR.effectdummy maps the <effectdummy> element under the <environment> node for the Korean‐locale format.

The parser correctly dispatches to root.effectdummy for default data and to dataKr.effectdummy for KR data, so there is no structural inconsistency.

Likely an incorrect or invalid review comment.

Maple2.File.Tests/ScriptParserTest.cs (3)

12-12: Explicit filter loading for NA locale.

The addition of explicit filter loading with "NA" and "Live" parameters ensures consistent test behavior across different environments and locales.

Also applies to: 31-31, 50-50


68-80: Test added for Korean NPC script parsing.

The test properly validates the Korean NPC script parsing functionality by:

  1. Loading the correct filter for the KR locale
  2. Using the appropriate XML reader
  3. Verifying valid IDs and non-null scripts
  4. Confirming the expected count of 3271 scripts

This test ensures the new Korean-specific parsing functionality works correctly.


82-94: Test added for Korean Quest script parsing.

The test properly validates the Korean Quest script parsing functionality by:

  1. Loading the correct filter for the KR locale
  2. Using the appropriate XML reader
  3. Verifying valid IDs and non-null scripts
  4. Confirming the expected count of 4291 scripts

This test ensures the new Korean-specific parsing functionality works correctly.

Maple2.File.Parser/ItemParser.cs (1)

19-20: Conditional serializer initialization based on locale.

The ItemSerializer is now correctly initialized based on the current locale, using ItemDataKR for the Korean locale and ItemDataRoot otherwise.

Maple2.File.Tests/SkillParserTest.cs (5)

2-2: Good addition for filter support.

Adding the Tools namespace import is necessary for the Filter.Load calls added throughout the file.


12-12: Nice initialization of locale and environment.

Setting up the Filter with appropriate "NA" and "Live" parameters before parsing ensures consistent test execution.


24-36: Well-structured KR skill parser test.

This test follows the same pattern as the NA test but correctly uses TestUtilsKR.XmlReader with "KR" locale, and calls the specialized ParseKR() method. The assertions verify positive IDs, non-null data, and the expected count of skills.


39-46: Good test for NA skill name loading.

This test isolates and verifies the LoadSkillNames functionality for the NA locale with the appropriate expected count.


48-55: Good test for KR skill name loading.

This test follows the same pattern as the NA name loading test but correctly uses TestUtilsKR.XmlReader with "KR" locale and verifies the expected count of Korean skill names.

Maple2.File.Parser/ScriptParser.cs (4)

3-3: New import for XML generation.

Adding the M2dXmlGenerator namespace import is necessary for XML serialization functionality.


19-19: Nice conditional XML serializer initialization.

This change enables the ScriptParser to deserialize either NpcScriptListKR for Korean locale or NpcScript for other locales based on the FeatureLocaleFilter.Locale value.


34-43: Well-implemented Korean NPC script parsing.

This method correctly handles the different structure of Korean NPC script data by:

  1. Looking for a single consolidated XML file ("npcscript_final.xml") instead of multiple files
  2. Deserializing into the appropriate NpcScriptListKR type
  3. Yielding individual NPC scripts with their IDs

The use of Debug.Assert ensures proper error detection during parsing.


56-65: Well-implemented Korean quest script parsing.

This method follows the same pattern as ParseNpcKR by targeting a single consolidated XML file ("questscript_final.xml") for Korean quest scripts, deserializing it, and yielding individual quest scripts.

Maple2.File.Tests/ItemParserTest.cs (4)

2-2: Good addition for filter support.

Adding the Tools namespace import is necessary for the Filter.Load calls added throughout the file.


12-12: Nice initialization of locale and environment.

Setting up the Filter with appropriate "NA" and "Live" parameters before parsing ensures consistent test execution.


20-28: Good implementation of item count tracking and verification.

Adding a counter to track the total number of parsed items and asserting the expected count provides stronger validation of the parsing process.


31-49: Well-structured KR item parser test.

This test follows the same pattern as the NA test but correctly uses TestUtilsKR.XmlReader with "KR" locale and parses with ItemDataKR. The assertions verify positive IDs, non-null data, and the expected count of items.

Maple2.File.Tests/ItemOptionParserTest.cs (5)

2-2: Good addition for filter support.

Adding the Tools namespace import is necessary for the Filter.Load calls added throughout the file.


11-11: Nice initialization of locale and environment in all test methods.

Setting up the Filter with appropriate "NA" and "Live" parameters before parsing in each test method ensures consistent test execution.

Also applies to: 27-27, 40-40, 50-50


61-84: Comprehensive test for Korean item options parsing.

This test properly validates the KR-specific parsing methods for constant and random options, including count verification. The commented section about static options provides important context that this option type may not exist in the Korean version.


86-97: Good test for Korean merge option parsing.

This test correctly validates the ParseMergeOptionBaseKR method with appropriate assertions on data and count.


108-119: Good test for Korean option variation parsing.

This test correctly validates the variation and variation equipment parsing for Korean data.

Maple2.File.Tests/NifParserTest.cs (1)

24-25: Good move to remove duplication
Delegating the heavy‑weight validation to a single helper makes the individual tests concise and easier to extend.

Maple2.File.Tests/NpcParserTest.cs (5)

12-12: Good use of the Filter class to ensure correct locale.

Adding the explicit locale loading ensures the proper context is set before parsing, which is especially important when testing both NA and KR data.


20-27: Improved test structure with proper count validation.

The updated test now has a proper count assertion to verify the exact number of NPCs parsed (7535), which is a good enhancement to the test coverage.


30-48: Well-structured KR parser test.

The Korean NPC parser test follows the same pattern as the NA test, with appropriate use of KR-specific utilities and assertions. The count verification (10795) ensures the correct number of entries are parsed.


50-63: Good addition of NPC name parsing test.

This test focuses specifically on parsing NPC names from the NA dataset, providing better test coverage for that specific functionality.


65-78: Comprehensive KR locale name parser test.

This test completes the test matrix by covering KR locale name parsing, maintaining consistency with the other test methods.

Maple2.File.Parser/ItemOptionParser.cs (3)

53-56: Good addition of KR-specific serializers.

The new serializer fields follow the naming convention of the existing ones and prepare for KR-specific XML deserialization.


65-68: Proper initialization of new serializers.

The initialization of KR-specific serializers with their corresponding types looks correct.


157-167: Good implementation of ParseMergeOptionBaseKR method.

This method correctly handles a single file without unnecessary looping.

Maple2.File.Parser/Xml/Table/ItemMergeOption.cs (3)

72-74: Well-structured root class for KR item merge options.

The ItemMergeOptionRootKR class follows the same XML root structure as the original class, correctly mapping to the KR XML format.


76-80: KR merge option class with simpler structure.

The MergeOptionKR class has a simpler structure than the original, directly containing Slot elements without the intermediate MergeStep class. This matches the KR XML structure.


82-87: Well-defined Slot class with option elements.

The Slot class is properly extended to include KR-specific option elements.

Maple2.File.Parser/Xml/ItemOptionConstant.cs (4)

30-33: Well-defined root class for KR item option constants.

The new ItemOptionConstantRootKR class correctly maps to the KR XML structure with an XML element list of options.


35-39: Clear item option constant class for KR format.

The ItemOptionConstant class for KR data includes the code attribute and a list of ranks, properly reflecting the hierarchical structure in the KR XML.


41-46: Well-structured rank class with appropriate attributes.

The ItemOptionConstantRank class includes grade and createType attributes and contains a list of option values, correctly mapping to the KR XML structure.


48-52: Comprehensive data class with detailed documentation.

The ItemOptionConstantDataKR class includes all necessary attributes and a helpful comment documenting all possible name values. This is excellent for future maintenance.

Maple2.File.Parser/QuestParser.cs (1)

21-23:

Details

❓ Verification inconclusive

questSerializer type mismatch when Locale == "KR"

When the locale is KR you instantiate the serializer with QuestDataRootKR, yet the Parse() method below still down‑casts the result to QuestDataRootRoot.
Calling Parse() while Locale == "KR" will therefore return null and trigger the Debug.Assert.

Two options:

  1. Guard the method:
if (FeatureLocaleFilter.Locale == "KR") 
    throw new InvalidOperationException("Use ParseKR() for the KR locale");
  1. Or create two dedicated serializers instead of one polymorphic field.

Pick whichever aligns better with the public surface you want to expose.


#!/bin/bash
set -e
# Locate QuestParser.cs
file=$(fd --absolute-path QuestParser.cs)
echo "Inspecting: $file"

# Show serializer instantiation around constructor
rg -n "XmlSerializer" -A3 "$file"

# Show the Parse method and its casting logic
rg -n "Parse(" -A10 "$file"

Address serializer mismatch for KR locale in QuestParser.cs

The constructor at Maple2.File.Parser/QuestParser.cs (around lines 21–23)

Type type = FeatureLocaleFilter.Locale == "KR"
    ? typeof(QuestDataRootKR)
    : typeof(QuestDataRootRoot);
questSerializer = new XmlSerializer(type);

always assigns a serializer for QuestDataRootKR when Locale == "KR", but the Parse() method below still casts the result to QuestDataRootRoot, leading to a null and a triggered Debug.Assert.

You’ll need to choose one of the following approaches to keep your public API consistent:

  • Guard the default Parse() method
    Immediately reject KR locale in Parse() so callers use a dedicated KR parser:
     // Inside Parse()
    + if (FeatureLocaleFilter.Locale == "KR")
    +     throw new InvalidOperationException("Use ParseKR() for the KR locale");
  • Maintain two serializers and parsing methods
    Introduce separate fields (e.g. questSerializerDefault and questSerializerKR) and corresponding Parse()/ParseKR() methods that return the correct root type without down‑casting.

Maple2.File.Parser/QuestParser.cs:

  • Constructor: serializer instantiation (lines 21–23)
  • Parse() method: casting logic needs updating

Pick the strategy that best aligns with your intended public surface.

Maple2.File.Parser/Xml/Table/JobTable.cs (1)

70-88: Inconsistent defaultWeaponSlot type between NA and KR models

JobTable.defaultWeaponSlot is string[] while the KR counterpart is a single int.
If this mirrors the real XML schema that’s fine, but downstream code that expects an array will break when fed a KR object.

Ensure all parsing/consuming code branches on locale before dereferencing this field, or standardise the property to one unified shape (e.g., always expose an int[] and map appropriately during deserialization).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
Maple2.File.Tests/TableParserKRTest.cs (2)

20-656: 🛠️ Refactor suggestion

Enhance test assertions for most test methods

Most test methods only iterate over parsing results without making assertions about the expected data. While this verifies no exceptions are thrown, it doesn't validate that the data is correct or complete.

Consider enhancing at least some of the critical test methods with assertions that verify:

  1. The expected number of items is parsed
  2. Key objects contain expected values
  3. Required properties are not null or empty

For example, similar to how TestParseSetItemOptionKr (lines 362-377) and TestIndividualItemDropKr (lines 386-393) include count assertions.

Here's a template for implementing improved assertions:

[TestMethod]
public void TestExampleImprovedMethod() {
    int count = 0;
    foreach ((int id, var item) in _parser.ParseExample()) {
        count++;
        // Add assertions for important items
        if (id == knownItemId) {
            Assert.IsNotNull(item.ImportantProperty);
            Assert.AreEqual(expectedValue, item.SomeProperty);
        }
    }
    // Verify total count is as expected
    Assert.IsTrue(count > 0, "No items were parsed");
    // If the exact count is stable, assert it
    // Assert.AreEqual(expectedCount, count);
}

165-169: ⚠️ Potential issue

Fix method call in TestGuildExpKr

The test method TestGuildExpKr incorrectly calls ParseGuildEvent() instead of what appears to be the intended ParseGuildExp(). This is likely a copy-paste error from the previous test method.

Apply this diff to fix the method call:

[TestMethod]
public void TestGuildExpKr() {
-    foreach ((_, _) in _parser.ParseGuildEvent()) {
+    foreach ((_, _) in _parser.ParseGuildExp()) {
        continue;
    }
}
🧹 Nitpick comments (1)
Maple2.File.Tests/TableParserKRTest.cs (1)

286-290: Remove obsolete assertions in TestParseJobTableKr

These commented-out assertions appear to reference properties (learn, startInvenItem, reward) that don't exist on the JobTableKR class or have a different structure in the Korean implementation.

Remove these obsolete commented-out assertions to keep the code clean and prevent confusion:

            Assert.IsTrue(job[0].skills.skills.Count > 0);
-            // Assert.IsTrue(job[0].learn.Count > 0);
-            // // Ensure the right amount of items are parsed
-            // Assert.AreEqual(job[0].startInvenItem.item.Count, itemCount);
-            // Assert.AreEqual(job[0].reward.item.Count, itemCount);

If you need to verify specific properties of the Korean job table, add new assertions for the actually available properties (e.g., job[0].startItems.Length).

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d0d4ca6 and b3e9dc3.

📒 Files selected for processing (26)
  • Maple2.File.Parser/ItemOptionParser.cs (6 hunks)
  • Maple2.File.Parser/ItemParser.cs (2 hunks)
  • Maple2.File.Parser/MapParser.cs (2 hunks)
  • Maple2.File.Parser/NpcParser.cs (2 hunks)
  • Maple2.File.Parser/PetParser.cs (1 hunks)
  • Maple2.File.Parser/QuestParser.cs (3 hunks)
  • Maple2.File.Parser/RidingParser.cs (2 hunks)
  • Maple2.File.Parser/ScriptParser.cs (4 hunks)
  • Maple2.File.Parser/SkillParser.cs (2 hunks)
  • Maple2.File.Parser/Xml/Map/Map.cs (1 hunks)
  • Maple2.File.Parser/Xml/Script/NpcScript.cs (1 hunks)
  • Maple2.File.Tests/AdditionalEffectParserTest.cs (3 hunks)
  • Maple2.File.Tests/FunctionCubeParserTest.cs (2 hunks)
  • Maple2.File.Tests/ItemOptionParserTest.cs (6 hunks)
  • Maple2.File.Tests/ItemParserTest.cs (2 hunks)
  • Maple2.File.Tests/MapParserTest.cs (2 hunks)
  • Maple2.File.Tests/NifParserTest.cs (2 hunks)
  • Maple2.File.Tests/NpcParserTest.cs (2 hunks)
  • Maple2.File.Tests/QuestParserTest.cs (2 hunks)
  • Maple2.File.Tests/RidingParserTest.cs (4 hunks)
  • Maple2.File.Tests/ScriptParserTest.cs (5 hunks)
  • Maple2.File.Tests/SkillParserTest.cs (3 hunks)
  • Maple2.File.Tests/TableParserKRTest.cs (1 hunks)
  • Maple2.File.Tests/TestUtils.cs (1 hunks)
  • Maple2.File.Tests/XBlockParserTest.cs (3 hunks)
  • global.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (19)
  • global.json
  • Maple2.File.Tests/AdditionalEffectParserTest.cs
  • Maple2.File.Tests/FunctionCubeParserTest.cs
  • Maple2.File.Tests/XBlockParserTest.cs
  • Maple2.File.Parser/Xml/Map/Map.cs
  • Maple2.File.Tests/ScriptParserTest.cs
  • Maple2.File.Parser/Xml/Script/NpcScript.cs
  • Maple2.File.Tests/SkillParserTest.cs
  • Maple2.File.Parser/ScriptParser.cs
  • Maple2.File.Tests/NifParserTest.cs
  • Maple2.File.Parser/RidingParser.cs
  • Maple2.File.Parser/QuestParser.cs
  • Maple2.File.Parser/ItemOptionParser.cs
  • Maple2.File.Tests/ItemOptionParserTest.cs
  • Maple2.File.Parser/SkillParser.cs
  • Maple2.File.Parser/NpcParser.cs
  • Maple2.File.Parser/ItemParser.cs
  • Maple2.File.Tests/NpcParserTest.cs
  • Maple2.File.Parser/MapParser.cs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (18)
Maple2.File.Parser/PetParser.cs (1)

40-40: Improves null safety

Using GetValueOrDefault(petId) ?? string.Empty ensures that when a pet name isn't found in the dictionary, an empty string is returned rather than null. This aligns with the pattern across the PR of using null-coalescing operators to provide safer string handling.

Maple2.File.Tests/RidingParserTest.cs (2)

12-12: Good initialization pattern

Explicitly loading the filter for the "NA" region before creating the parser ensures consistent test behavior and aligns with the changes across other test classes in this PR.

Also applies to: 27-27


40-58: Comprehensive KR data test coverage

The new test method for Korean riding data follows the same verification pattern as the NA tests while accounting for KR-specific data structures. The validation of passengers within riding objects and the assertion of the expected total count (615) provide good test coverage.

Maple2.File.Tests/MapParserTest.cs (3)

12-12: Improved test structure and validation

Adding the filter initialization and count validation ensures that the test is properly configured for the NA region and verifies the exact number of maps parsed (1200), providing stronger test assertions.

Also applies to: 20-27


30-48: Well-structured KR map parser test

This test follows the same verification pattern as the NA counterpart while accounting for the different dataset size in the KR version. The assertion of 1299 maps provides a clear validation point for the KR parsing functionality.


50-66: Good coverage for map name parsing

The addition of tests for ParseMapNames for both NA and KR locales ensures complete coverage of the map parsing functionality. The different count assertions (1152 for NA, 1282 for KR) properly validate the region-specific behavior.

Maple2.File.Tests/TestUtils.cs (2)

54-96: Well-structured utility class for KR testing

The new TestUtilsKr class provides a clean, centralized way to access Korean data files for testing, following the same pattern as the existing TestUtils class. The method replication ensures consistent behavior while maintaining a clear separation between NA and KR test environments.

While there is duplication between the classes, the separation provides clarity for region-specific testing purposes.


66-68: Appropriate environment validation

The check for the KMS2_DATA_FOLDER environment variable with a clear error message ensures that tests will fail early with a meaningful error if the required test data isn't available.

Maple2.File.Tests/ItemParserTest.cs (5)

12-12: Filter.Load now explicitly includes TestUtils.XmlReader

You've updated the Filter.Load call to explicitly pass TestUtils.XmlReader. This makes the dependency clearer and more explicit.


20-28: Improved test structure with count verification

Good addition of count tracking and verification with Assert.AreEqual(35309, count). This ensures the parser is processing the expected number of items, making the test more robust.


31-49: Well-structured KR locale test method

The new TestItemParserKr method follows good testing practices:

  1. It loads the appropriate KR filter
  2. Uses the Korean XML reader
  3. Verifies each parsed item
  4. Ensures the total count matches expectations

This provides good test coverage for the Korean locale implementation.


51-58: Good addition of ItemNames test for NA locale

This test correctly validates that the ItemNames() method returns the expected number of entries for the NA locale.


60-67: Good addition of ItemNames test for KR locale

This test complements the NA locale test by validating the ItemNames() method against Korean data.

Maple2.File.Tests/QuestParserTest.cs (5)

12-12: Filter.Load now explicitly includes TestUtils.XmlReader

You've updated the Filter.Load call to explicitly pass TestUtils.XmlReader. This makes the dependency clearer and more explicit.


20-27: Improved test structure with count verification

Good addition of count tracking and verification with Assert.AreEqual(4903, count). This ensures the parser is processing the expected number of quests, making the test more robust.


30-48: Well-implemented KR quest parser test

The new TestQuestParserKr method provides good test coverage for Korean quest data:

  1. It loads the appropriate KR filter
  2. Uses the Korean XML reader
  3. Uses the specialized ParseKr() method that returns QuestDataKR objects
  4. Verifies each parsed quest
  5. Ensures the total count matches expectations (6961)

This is a good addition for testing the new Korean locale support.


50-63: Good test coverage for quest descriptions

The new TestQuestDescriptionParser method adds test coverage for a previously untested feature - quest descriptions. It correctly:

  1. Validates that each quest description has a positive ID and non-null name
  2. Verifies the expected count of descriptions

This increases test coverage and confidence in the quest description parsing functionality.


65-78: Good test coverage for KR quest descriptions

This test complements the NA quest description test by validating the ParseQuestDescriptions() method against Korean data. The implementation is consistent with the other test methods and properly verifies the expected count (5793).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
Maple2.File.Tests/TableParserKRTest.cs (2)

19-27: Enhance test assertions for most test methods

Most test methods only iterate over parsing results without making assertions about the expected data. While this verifies no exceptions are thrown, it doesn't validate that the data is correct or complete.

Consider enhancing at least some of the critical test methods with assertions that verify:

  1. The expected number of items is parsed
  2. Key objects contain expected values
  3. Required properties are not null or empty

For example, similar to how TestParseSetItemOptionKR (lines 362-377) and TestIndividualItemDropKR (lines 386-393) include count assertions.

Here's a template for implementing improved assertions:

[TestMethod]
public void TestExampleImprovedMethod() {
    int count = 0;
    foreach ((int id, var item) in _parser.ParseExample()) {
        count++;
        // Add assertions for important items
        if (id == knownItemId) {
            Assert.IsNotNull(item.ImportantProperty);
            Assert.AreEqual(expectedValue, item.SomeProperty);
        }
    }
    // Verify total count is as expected
    Assert.IsTrue(count > 0, "No items were parsed");
    // If the exact count is stable, assert it
    // Assert.AreEqual(expectedCount, count);
}

Also applies to: 29-43, 45-113, 115-141, 143-190, 192-214, 216-256, 293-349, 355-361, 379-385, 395-428, 430-442, 444-463, 465-484, 486-506, 507-554, 577-613, 622-656


286-290: Remove obsolete assertions from TestParseJobTableKR

The commented‑out checks for learn, startInvenItem and reward refer to fields that don't exist on JobTableKR and should be removed.

-            // Assert.IsTrue(job[0].learn.Count > 0);
-            // // Ensure the right amount of items are parsed
-            // Assert.AreEqual(job[0].startInvenItem.item.Count, itemCount);
-            // Assert.AreEqual(job[0].reward.item.Count, itemCount);
🧹 Nitpick comments (2)
Maple2.File.Tests/TableParserKRTest.cs (2)

9-9: Consider standardizing class naming style

The class is named TableParserKrTest but elsewhere in the code "KR" is used (e.g., ParseJobTableKR()). Consider changing to TableParserKRTest for consistency.

-public class TableParserKrTest {
+public class TableParserKRTest {

19-27: Standardize method name suffix casing

Test method names are inconsistent in their suffix usage. Some use "Kr" (e.g., TestParseScrollKr) while others use "KR" (e.g., TestGuildExpKR). It would be better to standardize on one form, preferably "KR" to match the parsing method names.

For example:

-public void TestColorPaletteParserKr() {
+public void TestColorPaletteParserKR() {

And similar changes throughout the file.

Also applies to: 45-85, 115-141, 192-214, 293-349

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b3e9dc3 and 6eb1c43.

📒 Files selected for processing (3)
  • Maple2.File.Parser/Enum/ConditionType.cs (1 hunks)
  • Maple2.File.Tests/TableParserKRTest.cs (1 hunks)
  • Maple2.File.Tests/TableParserTest.cs (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • Maple2.File.Parser/Enum/ConditionType.cs
  • Maple2.File.Tests/TableParserTest.cs
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: format
🔇 Additional comments (5)
Maple2.File.Tests/TableParserKRTest.cs (5)

164-169: Test is now correctly marked as Ignored

The test method TestGuildExpKr is appropriately marked with [Ignore] and the method call is correctly using ParseGuildExp().


259-291: LGTM! Job table test has proper assertions

The test properly verifies job groups, features filtering, and skill counts. Good job on grouping jobs by job group ID to facilitate efficient testing and verification.


362-377: Well-implemented test with specific assertions

This test for TestParseSetItemOptionKr is well implemented with specific assertions for a known item ID (15123101) and verifies the total count of items parsed. This approach provides strong validation that the parser is working correctly.


386-393: Well-implemented test with count validation

This test correctly validates the total count of individual item drops, providing confidence that all expected data is being parsed.


563-575: Properly documented ignored tests

Tests are appropriately marked with [Ignore] attributes with clear comments indicating they're for features removed from KMS2 (Korean MapleStory 2). This is good practice to explain why tests are skipped.

Also applies to: 615-620

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
Maple2.File.Tests/TableParserKRTest.cs (2)

282-286: Remove obsolete assertions from TestParseJobTableKr

The commented-out checks for learn, startInvenItem and reward refer to fields that don't exist on JobTableKR and should be removed. If you need to verify KR-specific data, replace them with assertions against startItems (e.g. Assert.AreEqual(job[0].startItems.Length, itemCount)).


18-651: 🛠️ Refactor suggestion

Enhance test assertions for most test methods

Most test methods only iterate over parsing results without making assertions about the expected data. While this verifies no exceptions are thrown, it doesn't validate that the data is correct or complete.

Consider enhancing at least some of the critical test methods with assertions that verify:

  1. The expected number of items is parsed
  2. Key objects contain expected values
  3. Required properties are not null or empty

For example, similar to how TestParseSetItemOptionKr (lines 359-373) and TestIndividualItemDropKr (lines 383-389) include count assertions.

Here's a template for implementing improved assertions:

[TestMethod]
public void TestExampleImprovedMethod() {
    int count = 0;
    foreach ((int id, var item) in _parser.ParseExample()) {
        count++;
        // Add assertions for important items
        if (id == knownItemId) {
            Assert.IsNotNull(item.ImportantProperty);
            Assert.AreEqual(expectedValue, item.SomeProperty);
        }
    }
    // Verify total count is as expected
    Assert.IsTrue(count > 0, "No items were parsed");
    // If the exact count is stable, assert it
    // Assert.AreEqual(expectedCount, count);
}
Maple2.File.Parser/TableParser.cs (1)

755-765: ⚠️ Potential issue

Incorrect XML file used in ParseSetItemOptionKR().

You're using "table/setiteminfo.xml" but deserializing with setItemOptionKRSerializer into SetItemOptionRootKR. Based on previous comments, since KR doesn't have this feature, consider returning an empty collection instead.

The variable strinte is also defined but never used.

public IEnumerable<(int Id, SetItemOptionKR Option)> ParseSetItemOptionKR() {
-    IO.Crypto.Common.PackFileEntry entry = xmlReader.GetEntry("table/setiteminfo.xml");
-    var strinte = xmlReader.GetString(entry);
-    XmlReader reader = xmlReader.GetXmlReader(entry);
-    var data = setItemOptionKRSerializer.Deserialize(reader) as SetItemOptionRootKR;
-    Debug.Assert(data != null);
-
-    foreach (SetItemOptionKR option in data.option) {
-        yield return (option.id, option);
-    }
+    // KR doesn't have this XML because color palettes locked behind achievements wasn't a KMS2 thing
+    return Enumerable.Empty<(int Id, SetItemOptionKR Option)>();
}
🧹 Nitpick comments (2)
Maple2.File.Parser/TableParser.cs (2)

964-965: Remove extra blank lines.

There are two consecutive empty lines that should be removed to maintain consistent code formatting.

public IEnumerable<(int ItemId, ShopFurnishing UgcItem)> ParseFurnishingShopUgcAll() {
    string xml = Sanitizer.RemoveEmpty(xmlReader.GetString(xmlReader.GetEntry($"table/{locale}/shop_ugcall.xml")));
    xml = Sanitizer.RemoveUtf8Bom(xml);
-

    var reader = XmlReader.Create(new StringReader(xml));

259-264: Consistent locale-based file path handling across the codebase.

You've done a good job implementing locale-aware file path selection throughout the parser. This will make it easier to support both default and Korean locales.

For consistency, consider using a helper method for path construction to reduce code duplication.

// Add a private helper method:
private string GetLocalizedPath(string basePath, string fileName, bool useLocaleSubfolder = true) {
    if (useLocaleSubfolder) {
        return $"{basePath}/{locale}/{fileName}";
    } else if (locale == "kr") {
        return $"{basePath}/{fileName}";
    } else {
        return $"{basePath}/na/{fileName}";
    }
}

// Then use it like:
// string filePath = GetLocalizedPath("table", "dungeonroom.xml", false);
// Or:
// string filePath = GetLocalizedPath("table", "dungeonconfig.xml");

Also applies to: 302-304, 313-314, 323-324, 531-535, 546-547, 557-558, 914-915, 928-929, 967-969, 980-981, 991-992, 1069-1070, 1102-1103, 1135-1136, 1231-1232, 1297-1298, 1308-1309, 1374-1375

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6eb1c43 and 85dee17.

📒 Files selected for processing (2)
  • Maple2.File.Parser/TableParser.cs (33 hunks)
  • Maple2.File.Tests/TableParserKRTest.cs (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
Maple2.File.Tests/TableParserKRTest.cs (6)
Maple2.File.Parser/TableParser.cs (2)
  • TableParser (13-1383)
  • TableParser (105-204)
Maple2.File.Parser/Tools/Filter.cs (1)
  • Filter (9-47)
Maple2.File.Tests/TestUtils.cs (2)
  • TestUtilsKr (55-96)
  • TestUtilsKr (63-87)
Maple2.File.Parser/SkillParser.cs (1)
  • Dictionary (53-66)
Maple2.File.Parser/Xml/Table/JobTable.cs (1)
  • JobTableKR (76-88)
Maple2.File.Parser/Xml/Table/Feature.cs (1)
  • Feature (11-19)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: format
🔇 Additional comments (14)
Maple2.File.Tests/TableParserKRTest.cs (8)

1-16: Class initialization looks good!

The class initialization correctly sets up the TableParser with the KR locale and Live environment, which is essential for testing Korean-specific data parsing functionality.


160-165: Correctly marked as Ignored with appropriate comment

Good use of the [Ignore] attribute with a clear comment explaining why this test is skipped (feature removed from KMS2).


162-163: Fixed method call in TestGuildExpKr

This method correctly calls ParseGuildExp() which fixes the issue identified in a previous review where it incorrectly called ParseGuildEvent().


255-287: Good implementation with proper assertions

The TestParseJobTableKr method includes proper grouping of parsed job tables and meaningful assertions about the expected counts and feature filtering, which makes it a more thorough test than most others in this file.


359-373: Good assertions in TestParseSetItemOptionKr

This test method includes specific assertions verifying both particular item properties and the total count of parsed items, which makes it a more valuable test than those that just iterate through results.


383-389: Good count assertion in TestIndividualItemDropKr

This test method verifies the total count of parsed drops, which is a good validation check.


441-445: TestAdventureLevelAbilityKr is properly implemented

This test method correctly uses direct parsing without redundant operations that were flagged in previous reviews.


559-571: Correctly marked tests as Ignored

The TestSurvivalLevelKr and TestSurvivalLevelRewardKr methods are properly marked with [Ignore] attributes and include comments explaining they test features removed from KMS2.

Maple2.File.Parser/TableParser.cs (6)

354-354: Adding null check for fish names.

This change is necessary since GetValueOrDefault returns string? and we need to ensure a non-null value when it doesn't exist in the dictionary.


493-493: Good addition of null handling for name lookups.

Adding the null coalescing operator (??) to ensure that missing names default to empty string rather than null is a good defensive programming practice.

Also applies to: 741-741, 779-779


797-813: The Korean individual item drop parser looks well implemented.

The parser properly handles the Korean XML format which has a different structure than the default one. The sanitization steps (removing empty content, sanitizing booleans, and removing UTF-8 BOM) ensure proper parsing of the Korean data.


103-104: Good implementation of locale-based file path selection.

Adding the locale field and initializing it from FeatureLocaleFilter.Locale.ToLower() enables dynamic selection of XML file paths based on the current locale setting. This is a good approach for supporting multiple locales.

Also applies to: 195-196


618-627: Good implementation of the Korean job table parser.

The ParseJobTableKR method follows the same pattern as other parsers and correctly uses the jobKRSerializer to deserialize the Korean job data.


49-50: Good addition of Korean-specific serializers.

Adding dedicated serializers for Korean data types (jobKRSerializer, setItemOptionKRSerializer, and individualItemDropKRSerializer) is a good approach to handle the different XML schemas between locales.

Also applies to: 63-64, 66-67, 141-142, 155-156, 158-159

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🔭 Outside diff range comments (1)
Maple2.File.Parser/TableParser.cs (1)

783-797: ⚠️ Potential issue

Code indentation causing formatting issues

Several pipeline failures indicate whitespace formatting issues in this section. The nested anonymous object creation has incorrect indentation.

Fix the indentation to resolve formatting errors:

 public IEnumerable<(int Id, IDictionary<byte, List<IndividualItemDrop>>)> ParseIndividualItemDrop() {
     string xml = Sanitizer.RemoveEmpty(xmlReader.GetString(xmlReader.GetEntry("table/individualitemdrop.xml")));
     xml = Sanitizer.SanitizeBool(xml);
     var reader = XmlReader.Create(new StringReader(xml));
     var data = individualItemDropSerializer.Deserialize(reader) as IndividualItemDropRoot;
     Debug.Assert(data != null);
-    var groups = data.individualDropBox.GroupBy(individualItemDrop => new {
-            individualItemDrop.individualDropBoxID,
-            individualItemDrop.dropGroup
-        })
+    var groups = data.individualDropBox.GroupBy(individualItemDrop => new {
+        individualItemDrop.individualDropBoxID,
+        individualItemDrop.dropGroup
+    })
         .ToDictionary(group => group.Key, group => group.ToList());
     foreach (var group in groups) {
-        yield return (group.Key.individualDropBoxID, group.Value.GroupBy(drop => drop.dropGroup).ToDictionary(drop => drop.Key, drop => drop.ToList()));
+        yield return (group.Key.individualDropBoxID, 
+            group.Value.GroupBy(drop => drop.dropGroup)
+                .ToDictionary(drop => drop.Key, drop => drop.ToList()));
     }
 }

Apply the same indentation fix to similar blocks at lines 823-830, 839-846, 855-862, 871-878, 887-894, 903-910, 919-926, 935-942, and 951-958.

🧰 Tools
🪛 GitHub Actions: Format

[error] 790-790: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 791-791: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 792-792: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.

♻️ Duplicate comments (5)
Maple2.File.Parser/TableParser.cs (3)

755-765: ⚠️ Potential issue

Incorrect XML file used in ParseSetItemOptionKR()

You deserialize SetItemOptionRootKR but open "table/setiteminfo.xml" instead of the expected "table/setitemoption.xml" (or a locale‑specific variant).
This will deserialize the wrong schema and likely fail at runtime.

-IO.Crypto.Common.PackFileEntry entry = xmlReader.GetEntry("table/setiteminfo.xml");
+IO.Crypto.Common.PackFileEntry entry = xmlReader.GetEntry($"table/{locale}/setitemoption.xml");

strinte is also unused and can be removed.


755-765: ⚠️ Potential issue

Incorrect XML file used in ParseSetItemOptionKR()

You're deserializing SetItemOptionRootKR but opening "table/setiteminfo.xml" instead of the expected "table/setitemoption.xml" (or a locale-specific variant). Also, the strinte variable is unused.

-IO.Crypto.Common.PackFileEntry entry = xmlReader.GetEntry("table/setiteminfo.xml");
-var strinte = xmlReader.GetString(entry);
+IO.Crypto.Common.PackFileEntry entry = xmlReader.GetEntry($"table/{locale}/setitemoption.xml");
 XmlReader reader = xmlReader.GetXmlReader(entry);
 var data = setItemOptionKRSerializer.Deserialize(reader) as SetItemOptionRootKR;

755-765: ⚠️ Potential issue

Incorrect XML file used in ParseSetItemOptionKR()

You deserialize SetItemOptionRootKR but open "table/setiteminfo.xml" instead of the expected "table/setitemoption.xml".

-IO.Crypto.Common.PackFileEntry entry = xmlReader.GetEntry("table/setiteminfo.xml");
+IO.Crypto.Common.PackFileEntry entry = xmlReader.GetEntry($"table/{locale}/setitemoption.xml");

Also, strinte is unused and can be removed:

 IO.Crypto.Common.PackFileEntry entry = xmlReader.GetEntry("table/setiteminfo.xml");
-var strinte = xmlReader.GetString(entry);
 XmlReader reader = xmlReader.GetXmlReader(entry);
Maple2.File.Parser/QuestParser.cs (2)

1-8: ⚠️ Potential issue

Missing core using directives breaks compilation

The file uses types from System, System.Collections.Generic, and System.IO namespaces, but these are not imported. The code will fail to compile without these directives.

 using System.Diagnostics;
+using System;
+using System.Collections.Generic;
+using System.IO;
 using System.Xml;
 using System.Xml.Serialization;
 using M2dXmlGenerator;

57-75: ⚠️ Potential issue

Use dictionary indexer instead of Add to prevent exceptions

Using questNames.Add() will throw an exception if a duplicate key is encountered. This is likely to happen with quest IDs across multiple XML files.

 foreach (QuestDescription description in root.quest) {
-    questNames.Add(description.questID, description.name);
+    questNames[description.questID] = description.name;
 }
🧹 Nitpick comments (6)
Maple2.File.Parser/TableParser.cs (4)

808-813: Improve method chaining readability

The LINQ chain is quite complex and could be formatted more clearly to improve readability.

-yield return (dropBox.DropBoxID, dropBox.Groups
-    .GroupBy(g => (byte) g.DropGroupID)
-    .ToDictionary(
-        g => g.Key,
-        g => g.SelectMany(grp => grp.Items).ToList()
-    ));
+yield return (
+    dropBox.DropBoxID, 
+    dropBox.Groups
+        .GroupBy(g => (byte) g.DropGroupID)
+        .ToDictionary(
+            g => g.Key,
+            g => g.SelectMany(grp => grp.Items).ToList()
+        )
+);

987-987: Redundant empty line

There's an unnecessary empty line after the UTF-8 BOM removal.

 xml = Sanitizer.RemoveUtf8Bom(xml);
-
 var reader = XmlReader.Create(new StringReader(xml));

802-803: Consider adding comment explaining UTF-8 BOM removal

The code removes UTF-8 BOM from the XML string, but it's not clear why this is necessary. Adding a comment would help explain the purpose.

 xml = Sanitizer.SanitizeBool(xml);
+// Remove UTF-8 BOM to ensure proper XML parsing of Korean characters
 xml = Sanitizer.RemoveUtf8Bom(xml);

103-196: Locale initialization is good, but consider uppercase comparison

The locale initialization is well-implemented, but consider using case-insensitive comparison for better reliability.

-locale = FeatureLocaleFilter.Locale.ToLower();
+locale = FeatureLocaleFilter.Locale.ToLowerInvariant();
Maple2.File.Parser/QuestParser.cs (2)

25-40: Consider more robust error handling for file access

The Parse() method now correctly handles quest data parsing, but it doesn't have robust error handling for cases where XML entries might not exist or could be malformed.

Consider adding try-catch blocks to handle potential IO and XML deserialization exceptions:

 public IEnumerable<(int Id, string Name, QuestData Data)> Parse() {
     Dictionary<int, string> questNames = ParseQuestDescriptions();

     foreach (PackFileEntry entry in xmlReader.Files.Where(entry => entry.Name.StartsWith("quest/"))) {
-        var reader = XmlReader.Create(new StringReader(Sanitizer.SanitizeQuest(xmlReader.GetString(entry))));
-
-        var root = questSerializer.Deserialize(reader) as QuestDataRootRoot;
-        Debug.Assert(root != null);
+        try {
+            var reader = XmlReader.Create(new StringReader(Sanitizer.SanitizeQuest(xmlReader.GetString(entry))));
+
+            var root = questSerializer.Deserialize(reader) as QuestDataRootRoot;
+            if (root == null) continue;
+
+            QuestData? data = root.environment?.quest;
+            if (data == null) continue;
+
+            int questId = int.Parse(Path.GetFileNameWithoutExtension(entry.Name));
+            yield return (questId, questNames.GetValueOrDefault(questId, string.Empty), data);
+        } catch (Exception ex) {
+            Debug.WriteLine($"Error parsing quest file {entry.Name}: {ex.Message}");
+            continue;
+        }
-
-        QuestData? data = root.environment?.quest;
-        if (data == null) continue;
-
-        int questId = int.Parse(Path.GetFileNameWithoutExtension(entry.Name));
-        yield return (questId, questNames.GetValueOrDefault(questId, string.Empty), data);
     }
 }

42-55: Similar error handling needed for KR parser

The ParseKr() method has similar issues with error handling as the Parse() method.

Consider using a try-catch block to handle potential exceptions:

 public IEnumerable<(int Id, string Name, QuestDataKR Data)> ParseKr() {
     Dictionary<int, string> questNames = ParseQuestDescriptions();

     PackFileEntry? entry = xmlReader.GetEntry("questdata.xml");
     Debug.Assert(entry != null, "questdata.xml not found");
-    var reader = XmlReader.Create(new StringReader(Sanitizer.SanitizeQuest(xmlReader.GetString(entry))));
-
-    var root = questSerializer.Deserialize(reader) as QuestDataRootKR;
-    Debug.Assert(root != null);
-
-    foreach (QuestDataKR data in root.quests) {
-        yield return (data.id, questNames.GetValueOrDefault(data.id, string.Empty), data);
+    try {
+        var reader = XmlReader.Create(new StringReader(Sanitizer.SanitizeQuest(xmlReader.GetString(entry))));
+        
+        var root = questSerializer.Deserialize(reader) as QuestDataRootKR;
+        if (root == null) yield break;
+        
+        foreach (QuestDataKR data in root.quests) {
+            yield return (data.id, questNames.GetValueOrDefault(data.id, string.Empty), data);
+        }
+    } catch (Exception ex) {
+        Debug.WriteLine($"Error parsing KR quest data: {ex.Message}");
     }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85dee17 and 1547d0a.

📒 Files selected for processing (7)
  • Maple2.File.Parser/ItemParser.cs (2 hunks)
  • Maple2.File.Parser/MapParser.cs (2 hunks)
  • Maple2.File.Parser/NpcParser.cs (2 hunks)
  • Maple2.File.Parser/PetParser.cs (1 hunks)
  • Maple2.File.Parser/QuestParser.cs (3 hunks)
  • Maple2.File.Parser/SkillParser.cs (2 hunks)
  • Maple2.File.Parser/TableParser.cs (38 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • Maple2.File.Parser/PetParser.cs
  • Maple2.File.Parser/NpcParser.cs
  • Maple2.File.Parser/ItemParser.cs
  • Maple2.File.Parser/SkillParser.cs
  • Maple2.File.Parser/MapParser.cs
🧰 Additional context used
🧬 Code Graph Analysis (1)
Maple2.File.Parser/QuestParser.cs (5)
Maple2.File.Generator/Resource/FeatureLocaleFilter.cs (1)
  • FeatureLocaleFilter (7-76)
Maple2.File.Parser/PetParser.cs (2)
  • IEnumerable (25-42)
  • IEnumerable (44-50)
Maple2.File.Parser/Xml/Quest/Quest.cs (2)
  • QuestData (17-54)
  • QuestDataKR (62-64)
Maple2.File.IO/M2dReader.cs (3)
  • PackFileEntry (39-41)
  • XmlReader (43-45)
  • GetString (64-67)
Maple2.File.Parser/Tools/Sanitizer.cs (2)
  • Sanitizer (5-105)
  • SanitizeQuest (61-65)
🪛 GitHub Actions: Format
Maple2.File.Parser/TableParser.cs

[error] 790-790: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 791-791: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 792-792: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 824-824: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 825-825: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 826-826: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 840-840: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 841-841: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 842-842: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 856-856: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 857-857: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 858-858: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 872-872: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 873-873: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 874-874: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 888-888: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 889-889: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 890-890: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 904-904: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 905-905: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 906-906: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 920-920: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 921-921: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 922-922: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 936-936: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 937-937: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 938-938: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 952-952: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 953-953: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.


[error] 954-954: dotnet-format whitespace check failed: Fix whitespace formatting. Delete 4 characters.

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (15)
Maple2.File.Parser/TableParser.cs (14)

103-103: LGTM: Locale field for consistent path resolution

Good approach adding a locale field initialized from FeatureLocaleFilter.Locale to standardize locale-aware file path resolution throughout the class.

Also applies to: 195-195


354-354: LGTM: Safer dictionary lookups with GetValueOrDefault

Good improvement using GetValueOrDefault with empty string fallback for dictionary lookups. This prevents null reference exceptions when keys aren't found.

Also applies to: 493-493, 741-741, 779-779


618-627: LGTM: Well-implemented Korean job table parser

The new ParseJobTableKR method correctly handles parsing Korean-specific job data.


799-814: LGTM: Well-structured KR-specific item drop parser

The ParseIndividualItemDropKR method properly handles Korean-specific item drop data, including sanitization of XML content before deserialization.


987-988: LGTM: UTF-8 BOM handling

Good addition of UTF-8 BOM removal for XML deserialization. This helps prevent parsing errors with Korean character encoding.


259-262: LGTM: Locale-specific file path selection

Good implementation of conditional file path selection based on locale. This pattern is consistently applied throughout the file for various resource types.


49-64: Good serializer additions for Korean data formats

The new serializers for Korean-specific data types are correctly implemented.


258-270: Good locale-specific file path handling

The conditional selection of file paths based on locale is well-implemented.


302-310: Consistent locale path formatting

The string interpolation for locale paths is concise and readable.


354-355: Good null-safe handling of dictionary lookup

Using GetValueOrDefault with an empty string fallback ensures that no null values will be returned.


618-627: Well-structured KR job table parser

The implementation of ParseJobTableKR() is clean and follows the same pattern as other parsers.


799-815: Well-structured KR item drop parser

The implementation of ParseIndividualItemDropKR() is well organized and properly handles the Korean data format. The use of Sanitizer.RemoveUtf8Bom(xml) is a good addition to ensure proper handling of encoded files.


985-996: Good BOM handling for UGC XML

Adding UTF-8 BOM removal for UGC XML files is important for proper parsing.


1088-1096: Consistent use of locale for UGC design paths

The locale-specific path handling is consistent with other methods.

Maple2.File.Parser/QuestParser.cs (1)

18-23: Looks good - locale-aware serializer implementation

The constructor now correctly selects the appropriate serializer type based on the locale, allowing for proper deserialization of both standard and Korean quest data formats.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
Maple2.File.Parser/TableParser.cs (2)

790-796: Fixed indentation in anonymous object declarations.

The indentation has been fixed in the GroupBy expression, which should resolve the formatting pipeline errors.


755-765: ⚠️ Potential issue

Fix incorrect XML file path in ParseSetItemOptionKR().

The method is deserializing SetItemOptionRootKR but is using the wrong XML file path ("table/setiteminfo.xml" instead of "table/setitemoption.xml" or a locale-specific variant). This would result in deserializing the wrong schema.

Additionally, the strinte variable at line 757 is declared but never used.

Apply this fix:

-IO.Crypto.Common.PackFileEntry entry = xmlReader.GetEntry("table/setiteminfo.xml");
-var strinte = xmlReader.GetString(entry);
+IO.Crypto.Common.PackFileEntry entry = xmlReader.GetEntry($"table/{locale}/setitemoption.xml");
🧹 Nitpick comments (3)
Maple2.File.Parser/TableParser.cs (3)

258-262: Inconsistent locale path handling.

Some methods use explicit if-checks for locale, while others use string interpolation. Consider standardizing on one approach for better maintainability.

-string filename = "table/na/dungeonroom.xml";
-if (locale == "kr") {
-    filename = "table/dungeonroom.xml";
-}
-XmlReader reader = xmlReader.GetXmlReader(xmlReader.GetEntry(filename));
+string prefix = locale == "kr" ? "" : "na/";
+XmlReader reader = xmlReader.GetXmlReader(xmlReader.GetEntry($"table/{prefix}dungeonroom.xml"));

Or alternatively, use the direct string interpolation approach used in other methods:

-string filename = "table/na/dungeonroom.xml";
-if (locale == "kr") {
-    filename = "table/dungeonroom.xml";
-}
-XmlReader reader = xmlReader.GetXmlReader(xmlReader.GetEntry(filename));
+XmlReader reader = xmlReader.GetXmlReader(xmlReader.GetEntry($"table/{(locale == "kr" ? "" : "na/")}dungeonroom.xml"));

530-535: Duplicate code pattern.

This pattern of locale-specific file selection is repeated throughout the code. Consider extracting it to a helper method to improve maintainability.

+private string GetLocaleFilePath(string baseFilePath, string defaultLocale = "na") {
+    return locale == "kr" ? $"table/{baseFilePath}" : $"table/{defaultLocale}/{baseFilePath}";
+}

// Then use it like this:
-string filename = "table/na/itemextraction.xml";
-if (locale == "kr") {
-    filename = "table/itemextraction.xml";
-}
-string xml = Sanitizer.RemoveEmpty(xmlReader.GetString(xmlReader.GetEntry(filename)));
+string xml = Sanitizer.RemoveEmpty(xmlReader.GetString(xmlReader.GetEntry(GetLocaleFilePath("itemextraction.xml"))));

302-303: Consider error handling for missing locale-specific files.

The code assumes that every locale will have its own dungeon config file. Consider adding error handling in case a file doesn't exist for a specific locale.

-XmlReader reader = xmlReader.GetXmlReader(xmlReader.GetEntry($"table/{locale}/dungeonconfig.xml"));
+IO.Crypto.Common.PackFileEntry entry;
+try {
+    entry = xmlReader.GetEntry($"table/{locale}/dungeonconfig.xml");
+} catch (Exception) {
+    // Fallback to default locale
+    entry = xmlReader.GetEntry("table/na/dungeonconfig.xml");
+}
+XmlReader reader = xmlReader.GetXmlReader(entry);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1547d0a and 485898f.

📒 Files selected for processing (1)
  • Maple2.File.Parser/TableParser.cs (38 hunks)
🔇 Additional comments (7)
Maple2.File.Parser/TableParser.cs (7)

799-803: Good handling of UTF-8 BOM removal.

The addition of Sanitizer.RemoveUtf8Bom(xml) is good practice for handling Korean text files that might include a Byte Order Mark.


354-354: Good null-safety handling.

Using GetValueOrDefault with a default empty string is a good practice to handle missing fish names.


618-627: New Korean job table parsing functionality.

The new parsing method for Korean job tables is well-implemented. Consider adding unit tests to ensure the functionality works as expected.

Is there a corresponding unit test for this new functionality? It would be important to verify that the XML deserialization works correctly with Korean data structures.


986-988: Important UTF-8 BOM removal for UGC content.

The addition of UTF-8 BOM removal is particularly important for user-generated content files, as they might come from different sources with different text encodings.


807-814: Different structure for Korean drop data.

The Korean implementation has a different structure for handling drop data compared to the non-Korean version. This is a good design choice when dealing with different data schemas.


103-104: Locale field addition.

Adding the locale field is a good design choice for making the parser locale-aware.


195-196: Locale initialization.

The locale is properly initialized from the global FeatureLocaleFilter. This ensures consistency across the application.

@AngeloTadeucci AngeloTadeucci merged commit 32357e6 into master Apr 22, 2025
3 checks passed
@AngeloTadeucci AngeloTadeucci deleted the dev branch April 22, 2025 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants