MapleStory Classic World (mscw) WZ archive and .img property parser, reader, and writer library in C#.
Maple.Classic.File.IO:Archive/(Maple.Classic.File.IO.Archive):WzArchive,WzNode,WzHeaderValues/(Maple.Classic.File.IO.Values):WzProperty,WzCanvasFormat, and partialWzValuehierarchy (WzValue.cs,WzValue.Object.cs,WzValue.Canvas.cs,WzValue.Sound.cs,WzValue.Convex.cs,WzValue.RawData.cs)Serialization/(Maple.Classic.File.IO.Serialization): Internal binary/JSON serialization (WzReader,WzWriter,WzImage)Crypto/(Maple.Classic.File.IO.Crypto):WzCryptoversion hashing, offset encryption/decryption, and checksumsWzException.cs(Maple.Classic.File.IO):WzExceptionandWzErrorKind
Maple.Classic.File.Tests: Unit tests for string decoding, version hashing, offset encryption/decryption, directory traversal, property deserialization, and round-trip archive/image serialization.
using Maple.Classic.File.IO.Archive;
using var archive = new WzArchive("Data/String/String_000.wz");
foreach (WzNode node in archive.Nodes) {
Console.WriteLine($"{node.Name} ({node.Size} bytes)");
}using Maple.Classic.File.IO.Archive;
using Maple.Classic.File.IO.Values;
using var archive = new WzArchive("Data/String/String_000.wz");
WzValue eqp = archive.ParseImage("Eqp.img");
string? coatName = eqp["Eqp/Coat/1040000/name"]?.AsString();
Console.WriteLine(coatName);
// Render property tree to JSON
Console.WriteLine(eqp.ToJson());using Maple.Classic.File.IO.Archive;
using Maple.Classic.File.IO.Values;
using var archive = new WzArchive("Data/String/String_000.wz");
WzValue eqp = archive.ParseImage("Eqp.img");
// Implicit conversions and path-creating indexer
eqp["Eqp/Longcoat/1054555/name"] = "Frieren's Clothes";
eqp["Eqp/Longcoat/1054555/reqLevel"] = 10;
archive.SetImage("Eqp.img", eqp);
archive.Save("String_000.wz");