diff --git a/pkNX.Containers/Mini/MiniUtil.cs b/pkNX.Containers/Mini/MiniUtil.cs index b07db2b9..aad0bb1e 100644 --- a/pkNX.Containers/Mini/MiniUtil.cs +++ b/pkNX.Containers/Mini/MiniUtil.cs @@ -8,9 +8,9 @@ namespace pkNX.Containers; /// public static class MiniUtil { - public static byte[] PackMini(string folder, string identifier) => PackMini(Directory.GetFiles(folder), identifier); + public static byte[] PackMini(string folder, ReadOnlySpan identifier) => PackMini(Directory.GetFiles(folder), identifier); - public static byte[] PackMini(string[] files, string identifier) + public static byte[] PackMini(ReadOnlySpan files, ReadOnlySpan identifier) { byte[][] fileData = new byte[files.Length][]; for (int i = 0; i < fileData.Length; i++) @@ -18,7 +18,7 @@ public static byte[] PackMini(string[] files, string identifier) return PackMini(fileData, identifier); } - public static byte[] PackMini(byte[][] fileData, string identifier) + public static byte[] PackMini(byte[][] fileData, ReadOnlySpan identifier) { // Create new Binary with the relevant header bytes byte[] data = new byte[4]; @@ -60,13 +60,13 @@ public static byte[] PackMini(byte[][] fileData, string identifier) return newPack.ToArray(); } - public static byte[][] UnpackMini(string file, string identifier) + public static byte[][] UnpackMini(string file, ReadOnlySpan identifier) { byte[] fileData = FileMitm.ReadAllBytes(file); return UnpackMini(fileData, identifier); } - public static byte[][] UnpackMini(byte[] fileData, string identifier) + public static byte[][] UnpackMini(byte[] fileData, ReadOnlySpan identifier) { if (fileData.Length < 4) throw new ArgumentOutOfRangeException(nameof(fileData)); diff --git a/pkNX.Containers/VFS/FileSystems/Archives/ZipArchiveFileSystem.cs b/pkNX.Containers/VFS/FileSystems/Archives/ZipArchiveFileSystem.cs index ac3ab43e..20bf5f5f 100644 --- a/pkNX.Containers/VFS/FileSystems/Archives/ZipArchiveFileSystem.cs +++ b/pkNX.Containers/VFS/FileSystems/Archives/ZipArchiveFileSystem.cs @@ -9,46 +9,22 @@ namespace pkNX.Containers.VFS; public class ZipArchiveFileSystem : IFileSystem { public ZipArchive ZipArchive { get; } - public bool IsReadOnly => false; + private ZipArchiveFileSystem(ZipArchive archive) => ZipArchive = archive; - public static ZipArchiveFileSystem Open(Stream s) - { - return new ZipArchiveFileSystem(new ZipArchive(s, ZipArchiveMode.Update, true)); - } + public static ZipArchiveFileSystem Open(Stream s) => new(new ZipArchive(s, ZipArchiveMode.Update, true)); + public static ZipArchiveFileSystem Create(Stream s) => new(new ZipArchive(s, ZipArchiveMode.Create, true)); - public static ZipArchiveFileSystem Create(Stream s) - { - return new ZipArchiveFileSystem(new ZipArchive(s, ZipArchiveMode.Create, true)); - } + public void Dispose() => ZipArchive.Dispose(); - private ZipArchiveFileSystem(ZipArchive archive) - { - ZipArchive = archive; - } - public void Dispose() - { - ZipArchive.Dispose(); - } + protected IEnumerable GetZipEntries() => ZipArchive.Entries; - protected IEnumerable GetZipEntries() - { - return ZipArchive.Entries; - } - protected FileSystemPath ToPath(ZipArchiveEntry entry) - { - return FileSystemPath.Parse(FileSystemPath.DirectorySeparator + entry.FullName); - } - protected string ToEntryPath(FileSystemPath path) - { - // Remove heading '/' from path. - return path.Path.TrimStart(FileSystemPath.DirectorySeparator); - } + protected FileSystemPath ToPath(ZipArchiveEntry entry) => FileSystemPath.Parse(FileSystemPath.DirectorySeparator + entry.FullName); - protected ZipArchiveEntry? ToEntry(FileSystemPath path) - { - return ZipArchive.GetEntry(ToEntryPath(path)); - } + // Remove heading '/' from path. + protected string ToEntryPath(FileSystemPath path) => path.Path.TrimStart(FileSystemPath.DirectorySeparator); + + protected ZipArchiveEntry? ToEntry(FileSystemPath path) => ZipArchive.GetEntry(ToEntryPath(path)); public IEnumerable GetEntitiesInDirectory(FileSystemPath directory, Func? filter = null) { @@ -128,7 +104,7 @@ public void CreateDirectory(FileSystemPath path) public void Delete(FileSystemPath path, DeleteMode mode = DeleteMode.TopMostLayer) { - ZipArchiveEntry? entry = ZipArchive.GetEntry(ToEntryPath(path)); - entry?.Delete(); + if (ZipArchive.GetEntry(ToEntryPath(path)) is { } x) + x.Delete(); } } diff --git a/pkNX.Structures.FlatBuffers.LGPE/Gen7/EncounterTableUtil.cs b/pkNX.Structures.FlatBuffers.LGPE/Gen7/EncounterTableUtil.cs index 9da823b3..48f0fbf5 100644 --- a/pkNX.Structures.FlatBuffers.LGPE/Gen7/EncounterTableUtil.cs +++ b/pkNX.Structures.FlatBuffers.LGPE/Gen7/EncounterTableUtil.cs @@ -4,12 +4,12 @@ namespace pkNX.Structures.FlatBuffers.LGPE; public static class EncounterTableUtil { - public static IEnumerable GetLines(EncounterArchive t, string[] names, string[] species) + public static IEnumerable GetLines(EncounterArchive t, string[] metLocationNames, string[] species) { for (var i = 0; i < t.Table.Count; i++) { var enc = t.Table[i]; - yield return $"{i:000} - {names[i]}"; + yield return $"{i:000} - {metLocationNames[i]}"; if (enc.GroundTableEncounterRate != 0) { diff --git a/pkNX.Structures.FlatBuffers.LGPE/Gen7/ShopInventory.cs b/pkNX.Structures.FlatBuffers.LGPE/Gen7/ShopInventory.cs index 2d6fe0bd..fe4b7ae0 100644 --- a/pkNX.Structures.FlatBuffers.LGPE/Gen7/ShopInventory.cs +++ b/pkNX.Structures.FlatBuffers.LGPE/Gen7/ShopInventory.cs @@ -16,107 +16,11 @@ public partial class SingleShop { public override string ToString() => $"{Hash:X16} - {Inventories}"; - public readonly Dictionary LGPE = new() + public static readonly Dictionary LGPE = new() { { 14688060730225415067, "Celadon Department Store [TMs]" }, { 04251032178319698087, "Celadon Department Store [Evolution Stones]" }, }; - - public readonly Dictionary SWSH = new() - { - // Galar - { 0x1F3FF031A3A24490, "Poké Mart [0 Badges, Before Catching Tutorial]" }, - { 0x8E308F85B43038B4, "Motostoke [Upper Tier, TMs]" }, - { 0x8E309085B4303A67, "Hammerlocke [West, TMs]" }, - { 0x8E309185B4303C1A, "Hammerlocke [East, TMs]" }, - { 0x8E309285B4303DCD, "Wyndon [North, TMs]" }, - { 0x8E308B85B43031E8, "Battle Tower [TMs]" }, - { 0xCBD67969D873539B, "Motostoke [Lower Tier, Miscellaneous]" }, - { 0xCBD67869D87351E8, "Hammerlocke [South, Miscellaneous]" }, - { 0xCBD669D8735701, "Wyndon [South, Miscellaneous]" }, - { 0x04D7046DA09D3C78, "Hulbury [Herb Shop]" }, - { 0x4B2F9E98DDCB0707, "Hulbury [Incense Shop]" }, - { 0xE379CDF67A297070, "Wedgehurst [Berry Shop]" }, - { 0x3FD7A44219BF30BB, "Hammerlocke [South, BP Shop]" }, - { 0x3FD7A34219BF2F08, "Battle Tower [Battle Items]" }, - { 0x3FD7A64219BF3421, "Battle Tower [Nature Mints]" }, - // 0xD1BEA92EAAE52B5A -- Wishing Piece + X Items... unused? - - // Wild Area - // next 84 tables are all Ingredient Sellers with similar inventories that rotate daily; don't bother labeling (why hardcode everything GF?) - { 0xD1BEAA2EAAE52D0D, "Watt Trader 1 [Net Ball]" }, - { 0xD1BEA72EAAE527F4, "Watt Trader 1 [Dive Ball]" }, - { 0xD1BEA82EAAE529A7, "Watt Trader 1 [Nest Ball]" }, - { 0xD1BEA52EAAE5248E, "Watt Trader 1 [Repeat Ball]" }, - { 0xD1BEA62EAAE52641, "Watt Trader 1 [Timer Ball]" }, - { 0xD1BEA32EAAE52128, "Watt Trader 1 [Luxury Ball]" }, - { 0xD1BEA42EAAE522DB, "Watt Trader 1 [Dusk Ball]" }, - { 0xD1BEA12EAAE51DC2, "Watt Trader 1 [Heal Ball]" }, - { 0xD1BEA22EAAE51F75, "Watt Trader 1 [Quick Ball]" }, - - { 0xD1C20F2EAAE80E83, "Watt Trader 2 [Net Ball]" }, - { 0xD1C20E2EAAE80CD0, "Watt Trader 2 [Dive Ball]" }, - { 0xD1C2112EAAE811E9, "Watt Trader 2 [Nest Ball]" }, - { 0xD1C2102EAAE81036, "Watt Trader 2 [Repeat Ball]" }, - { 0xD1C2132EAAE8154F, "Watt Trader 2 [Timer Ball]" }, - { 0xD1C2122EAAE8139C, "Watt Trader 2 [Luxury Ball]" }, - { 0xD1C2152EAAE818B5, "Watt Trader 2 [Dusk Ball]" }, - { 0xD1C2142EAAE81702, "Watt Trader 2 [Heal Ball]" }, - { 0xD1C2172EAAE81C1B, "Watt Trader 2 [Quick Ball]" }, - - { 0xD1C2162EAAE81A68, "Watt Trader 3 [Net Ball]" }, - { 0xD1B79D2EAADEF848, "Watt Trader 3 [Dive Ball]" }, - { 0xD1B79E2EAADEF9FB, "Watt Trader 3 [Nest Ball]" }, - { 0xD1B79F2EAADEFBAE, "Watt Trader 3 [Repeat Ball]" }, - { 0xD1B7A02EAADEFD61, "Watt Trader 3 [Timer Ball]" }, - { 0xD1B7A12EAADEFF14, "Watt Trader 3 [Luxury Ball]" }, - { 0xD1B7A22EAADF00C7, "Watt Trader 3 [Dusk Ball]" }, - { 0xD1B7A32EAADF027A, "Watt Trader 3 [Heal Ball]" }, - { 0xD1B7A42EAADF042D, "Watt Trader 3 [Quick Ball]" }, - - { 0xD1B7952EAADEEAB0, "Watt Trader 4 [Net Ball]" }, - { 0xD1B7962EAADEEC63, "Watt Trader 4 [Dive Ball]" }, - { 0xD1BB232EAAE211D1, "Watt Trader 4 [Nest Ball]" }, - { 0xD1BB222EAAE2101E, "Watt Trader 4 [Repeat Ball]" }, - { 0xD1BB212EAAE20E6B, "Watt Trader 4 [Timer Ball]" }, - { 0xD1BB202EAAE20CB8, "Watt Trader 4 [Luxury Ball]" }, - { 0xD1BB272EAAE2189D, "Watt Trader 4 [Dusk Ball]" }, - { 0xD1BB262EAAE216EA, "Watt Trader 4 [Heal Ball]" }, - { 0xD1BB252EAAE21537, "Watt Trader 4 [Quick Ball]" }, - - { 0xD1BB242EAAE21384, "Watt Trader 5 [Net Ball]" }, - { 0xD1BB1B2EAAE20439, "Watt Trader 5 [Dive Ball]" }, - { 0xD1BB1A2EAAE20286, "Watt Trader 5 [Nest Ball]" }, - { 0xD1CC212EAAF0819E, "Watt Trader 5 [Repeat Ball]" }, - { 0xD1CC222EAAF08351, "Watt Trader 5 [Timer Ball]" }, - { 0xD1CC1F2EAAF07E38, "Watt Trader 5 [Luxury Ball]" }, - { 0xD1CC202EAAF07FEB, "Watt Trader 5 [Dusk Ball]" }, - { 0xD1CC252EAAF0886A, "Watt Trader 5 [Heal Ball]" }, - { 0xD1CC262EAAF08A1D, "Watt Trader 5 [Quick Ball]" }, - - { 0xD1CC232EAAF08504, "Watt Trader 6 [Net Ball]" }, - { 0xD1CC242EAAF086B7, "Watt Trader 6 [Dive Ball]" }, - { 0xD1CC192EAAF07406, "Watt Trader 6 [Repeat Ball]" }, - { 0xD1CC1A2EAAF075B9, "Watt Trader 6 [Quick Ball]" }, - { 0xD1CFA72EAAF39B27, "Watt Trader 6 [Heal Ball]" }, - - // Isle of Armor - { 0x5870C0165650F6A5, "Fields of Honor [Berry Shop]" }, - - // Crown Tundra - { 0x81DA6390A03C7E3F, "Freezington [Peddler]" }, - { 0x813C350B0B777943, "Snowslide Slope [Today's Highlight, TR00-TR09]" }, - { 0x813C360B0B777AF6, "Snowslide Slope [Today's Highlight, TR10-TR19]" }, - { 0x813C370B0B777CA9, "Snowslide Slope [Today's Highlight, TR20-TR29]" }, - { 0x813C380B0B777E5C, "Snowslide Slope [Today's Highlight, TR30-TR39]" }, - { 0x813C390B0B77800F, "Snowslide Slope [Today's Highlight, TR40-TR49]" }, - { 0x813C3A0B0B7781C2, "Snowslide Slope [Today's Highlight, TR50-TR59]" }, - { 0x813C3B0B0B778375, "Snowslide Slope [Today's Highlight, TR60-TR69]" }, - { 0x813C3C0B0B778528, "Snowslide Slope [Today's Highlight, TR70-TR79]" }, - { 0x813C3D0B0B7786DB, "Snowslide Slope [Today's Highlight, TR80-TR89]" }, - { 0x813F3A0B0B79B799, "Snowslide Slope [Today's Highlight, TR90-TR99]" }, - { 0xF49C86F8683842BF, "Max Lair [Dynite Ore Trader]" }, - }; } [TypeConverter(typeof(ExpandableObjectConverter))] @@ -124,16 +28,10 @@ public partial class MultiShop { public override string ToString() => $"{Hash:X16} - {string.Join(", ", Inventories.Select(z => z.ToString()))}"; - public readonly Dictionary LGPE = new() + public static readonly Dictionary LGPE = new() { { 0x66CA73B2966BB871, "Poké Mart Inventories [0-8 Badges]" }, }; - - public readonly Dictionary SWSH = new() - { - { 0x66CA73B2966BB871, "Poké Mart Inventories [0-8 Badges]" }, - { 0x5870BD165650F18C, "Fields of Honor [Watt Trader, 0-8 Badges]" }, - }; } [TypeConverter(typeof(ExpandableObjectConverter))] diff --git a/pkNX.Structures.FlatBuffers.Reflection/ReflectionDumpSchema.cs b/pkNX.Structures.FlatBuffers.Reflection/ReflectionDumpSchema.cs index ad8406bd..6f0cf054 100644 --- a/pkNX.Structures.FlatBuffers.Reflection/ReflectionDumpSchema.cs +++ b/pkNX.Structures.FlatBuffers.Reflection/ReflectionDumpSchema.cs @@ -14,14 +14,14 @@ public static class SchemaDump /// /// /// - public static Schema HandleReflection(byte[] data, string filePath, string dir, SchemaDumpSettings settings) + public static Schema HandleReflection(Memory data, ReadOnlySpan filePath, string dir, SchemaDumpSettings settings) { var schema = Schema.Serializer.Parse(data, FlatBufferDeserializationOption.GreedyMutable); DumpSchema(schema, filePath, dir, settings); return schema; } - public static void DumpSchema(Schema schema, string filePath, string dir, SchemaDumpSettings settings) + public static void DumpSchema(Schema schema, ReadOnlySpan filePath, string dir, SchemaDumpSettings settings) { var rootName = schema.RootTable?.Name ?? Path.GetFileNameWithoutExtension(filePath); @@ -36,7 +36,7 @@ public static void DumpSchema(Schema schema, string filePath, string dir, Schema DumpSchema(schema, fbs, cs, settings); } - public static void DumpSchema(byte[] data, TextWriter fbs, TextWriter cs, SchemaDumpSettings settings) + public static void DumpSchema(Memory data, TextWriter fbs, TextWriter cs, SchemaDumpSettings settings) { var schema = Schema.Serializer.Parse(data, FlatBufferDeserializationOption.GreedyMutable); DumpSchema(schema, fbs, cs, settings); @@ -54,7 +54,7 @@ public static void DumpSchema(Schema schema, TextWriter fbs, TextWriter cs, Sche fbs.WriteLine($"root_type {x};"); } - private static void WriteHeaderFBS(Schema schema, TextWriter fbs, string fileNameSpace) + private static void WriteHeaderFBS(Schema schema, TextWriter fbs, ReadOnlySpan fileNameSpace) { fbs.WriteLine($"namespace {fileNameSpace};"); fbs.WriteLine(); @@ -71,7 +71,7 @@ private static void WriteHeaderFBS(Schema schema, TextWriter fbs, string fileNam fbs.WriteLine($"// Enum Count: {schema.Enums.Count}"); } - private static void WriteHeaderCS(Schema schema, TextWriter cs, string fileNameSpace) + private static void WriteHeaderCS(Schema schema, TextWriter cs, ReadOnlySpan fileNameSpace) { cs.WriteLine("using System.Collections.Generic;"); cs.WriteLine("using System.ComponentModel;"); diff --git a/pkNX.Structures.FlatBuffers.Reflection/SchemaDump.cs b/pkNX.Structures.FlatBuffers.Reflection/SchemaDump.cs deleted file mode 100644 index 45e7c1c9..00000000 --- a/pkNX.Structures.FlatBuffers.Reflection/SchemaDump.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using FlatSharp; - -namespace pkNX.Structures.FlatBuffers.Reflection; - -/// -/// Exports fbs, cs -/// -public static class SchemaDumpOld -{ - public static Schema HandleReflection(byte[] data, string filePath, string dir, SchemaDumpSettings settings) - { - var schema = Schema.Serializer.Parse(data, FlatBufferDeserializationOption.GreedyMutable); - DumpSchema(schema, filePath, dir, settings); - return schema; - } - - public static void DumpSchema(Schema schema, string filePath, string dir, SchemaDumpSettings settings) - { - var rootName = schema.RootTable?.Name ?? Path.GetFileNameWithoutExtension(filePath); - - var fileCS = Path.Combine(dir, $"{rootName}.cs"); - using var fsCS = File.Create(fileCS); - using var cs = new StreamWriter(fsCS); - - var fileFBS = Path.Combine(dir, $"{rootName}.cs"); - using var fsFBS = File.Create(fileFBS); - using var fbs = new StreamWriter(fsFBS); - - DumpSchema(schema, fbs, cs, settings); - } - - public static void DumpSchema(byte[] data, TextWriter fbs, TextWriter cs, SchemaDumpSettings settings) - { - var schema = Schema.Serializer.Parse(data, FlatBufferDeserializationOption.GreedyMutable); - DumpSchema(schema, fbs, cs, settings); - } - - public static void DumpSchema(Schema schema, TextWriter fbs, TextWriter cs, SchemaDumpSettings settings) - { - WriteHeaderFBS(schema, fbs, settings.FileNamespace); - WriteHeaderCS(schema, cs, settings.FileNamespace); - - DumpEnums(schema, fbs, settings.StripNamespace); - DumpObjects(schema, fbs, cs, settings.StripNamespace); - - if (schema.RootTable?.Name is { } x) - fbs.WriteLine($"root_type {x};"); - } - - private static void WriteHeaderFBS(Schema schema, TextWriter fbs, string fileNameSpace) - { - fbs.WriteLine($"namespace {fileNameSpace};"); - fbs.WriteLine(); - fbs.WriteLine("attribute \"fs_vector\";"); - fbs.WriteLine("attribute \"fs_serializer\";"); - fbs.WriteLine("attribute \"fs_valueStruct\";"); - fbs.WriteLine("attribute \"fs_nonVirtual\";"); - fbs.WriteLine("attribute \"fs_unsafeStructVector\";"); - fbs.WriteLine(); - fbs.WriteLine("// Generated by FlatSharp"); - fbs.WriteLine($"// FileIdentifier: {schema.FileIdent}"); - fbs.WriteLine($"// FileExtension: {schema.FileExt}"); - fbs.WriteLine($"// Object Count: {schema.Objects.Count}"); - fbs.WriteLine($"// Enum Count: {schema.Enums.Count}"); - } - - private static void WriteHeaderCS(Schema schema, TextWriter cs, string fileNameSpace) - { - cs.WriteLine("using System.Collections.Generic;"); - cs.WriteLine("using System.ComponentModel;"); - cs.WriteLine("using FlatSharp.Attributes;"); - cs.WriteLine("// ReSharper disable UnusedMember.Global"); - cs.WriteLine("// ReSharper disable ClassNeverInstantiated.Global"); - cs.WriteLine("// ReSharper disable UnusedType.Global"); - cs.WriteLine("#nullable disable"); - cs.WriteLine(); - cs.WriteLine($"namespace {fileNameSpace};"); - cs.WriteLine(); - cs.WriteLine("// Generated by FlatSharp"); - cs.WriteLine($"// FileIdentifier: {schema.FileIdent}"); - cs.WriteLine($"// FileExtension: {schema.FileExt}"); - cs.WriteLine($"// Object Count: {schema.Objects.Count}"); - cs.WriteLine($"// Enum Count: {schema.Enums.Count}"); - cs.WriteLine($"// Root Type: {schema.RootTable?.Name ?? "None Specified"}"); - } - - private static ReadOnlySpan GetName(ReadOnlySpan defName, bool stripNamespace) - { - if (!stripNamespace) - return defName; - var idx = defName.LastIndexOf('.'); - return idx < 0 ? defName : defName[(idx + 1)..]; - } - - private static void DumpObjects(Schema schema, TextWriter fbs, TextWriter cs, bool stripNamespace) - { - var list = schema.Objects; - for (var i = list.Count - 1; i >= 0; i--) - { - var obj = list[i]; - - cs.WriteLine(); - cs.WriteLine("[TypeConverter(typeof(ExpandableObjectConverter))]"); - cs.WriteLine($"public partial {(obj.IsStruct ? "struct" : "class")} {GetName(obj.Name, stripNamespace)} {{ }}"); - - DumpObjectFBS(schema, fbs, stripNamespace, obj); - } - } - - private static void DumpObjectFBS(Schema schema, TextWriter fbs, bool stripNamespace, Object def) - { - fbs.WriteLine(); - fbs.Write(def.IsStruct ? "struct" : "table"); - fbs.Write(" "); - fbs.Write(GetName(def.Name, stripNamespace)); - if (schema.RootTable?.Name == def.Name) - fbs.Write(" (fs_serializer)"); - fbs.WriteLine(" {"); // end of class header - - // Write fields to fbs - foreach (var field in def.Fields.OrderBy(z => z.Id)) - { - fbs.Write(" "); - fbs.Write(field.Name); - fbs.Write(":"); - fbs.Write(field.Type.ToFBS(schema, field.Id)); - - WriteAttributes(fbs, field); - - fbs.WriteLine(";"); // end of line - } - fbs.WriteLine("}"); - } - - private static void WriteAttributes(TextWriter fbs, Field field) - { - bool any = false; - - void Write(string value) - { - fbs.Write(!any ? " (" : ", "); - fbs.Write(value); - any = true; - } - - if (field.Key) - Write("key"); - if (field.Required) - Write("required"); - if (field.Optional) - Write("optional"); - if (field.Deprecated) - Write("deprecated"); - - if (any) - fbs.Write(")"); - } - - private static void DumpEnums(Schema schema, TextWriter fbs, bool stripNamespace) - { - var list = schema.Enums; - for (var i = 0; i < list.Count; i++) - { - var def = list[i]; - fbs.WriteLine(); - - var typeName = def.UnderlyingType.ToFBS(schema, i, true); - var implType = $" : {typeName}"; - var defName = GetName(def.Name, stripNamespace); - fbs.WriteLine($"enum {defName}{implType}"); - fbs.WriteLine("{"); - { - for (int j = 0; j < def.Values.Count; j++) - { - var value = def.Values[j]; - fbs.WriteLine($" {j} = {value},"); - } - } - fbs.WriteLine("}"); - } - } - - private static string ToFBS(this Type type, Schema schema, int index, bool force = false) - { - var size = type.FixedLength; - var sizeStr = size > 0 ? $":{size}" : ""; - - if (index != -1) - { - var idx = type.Index; - if (type.BaseType == BaseType.Array) - return $"[{GetName(schema, idx, type.Element)}{sizeStr}]"; - if (type.BaseType == BaseType.Vector) - return $"[{GetName(schema, idx, type.Element)}{sizeStr}]"; - if (type.BaseType == BaseType.Obj) - return $"{schema.Objects[idx].Name}"; - if (!force) - return $"{schema.Enums[idx].Name}"; - } - - var baseType = type.BaseType; - if (baseType is BaseType.Array) - return $"[{GetName(type.Element)}{sizeStr}]"; - if (baseType is BaseType.Vector) - return $"[{GetName(type.Element)}{sizeStr}]"; - - var x = GetName(baseType); - if (type.Element != BaseType.None) - return $"[{x}]"; - return x; - } - - public static string GetName(BaseType type) => type.ToString().ToLower(); - - private static string GetName(Schema schema, int idx, BaseType type) - { - if (type is BaseType.Obj) - return schema.Objects[idx].Name; - return schema.Enums[idx].Name; - } -} diff --git a/pkNX.Structures.FlatBuffers.Reflection/SchemaDumpSettings.cs b/pkNX.Structures.FlatBuffers.Reflection/SchemaDumpSettings.cs index dbb329d3..7ce237f2 100644 --- a/pkNX.Structures.FlatBuffers.Reflection/SchemaDumpSettings.cs +++ b/pkNX.Structures.FlatBuffers.Reflection/SchemaDumpSettings.cs @@ -5,6 +5,6 @@ namespace pkNX.Structures.FlatBuffers.Reflection; /// public sealed record SchemaDumpSettings { - public bool StripNamespace { get; set; } = true; - public string FileNamespace { get; set; } = "pkNX.Structures.FlatBuffers"; + public bool StripNamespace { get; init; } = true; + public string FileNamespace { get; init; } = "pkNX.Structures.FlatBuffers"; } diff --git a/pkNX.Structures.FlatBuffers.SWSH/Gen8/Other/CellTable.cs b/pkNX.Structures.FlatBuffers.SWSH/Gen8/Other/CellTable.cs index 01b570f7..0e9c42a2 100644 --- a/pkNX.Structures.FlatBuffers.SWSH/Gen8/Other/CellTable.cs +++ b/pkNX.Structures.FlatBuffers.SWSH/Gen8/Other/CellTable.cs @@ -41,17 +41,14 @@ public partial class CellMetaQuad [TypeConverter(typeof(ExpandableObjectConverter))] public partial struct CellUnion { - public override string ToString() + public override string ToString() => Discriminator switch { - return Discriminator switch - { - 1 => Item1.ToString(), - 2 => Item2.ToString(), - 3 => Item3.ToString(), - 4 => Item4.ToString(), - _ => $"Unrecognized: {Discriminator}", - }; - } + 1 => Item1.ToString(), + 2 => Item2.ToString(), + 3 => Item3.ToString(), + 4 => Item4.ToString(), + _ => $"Unrecognized: {Discriminator}", + }; } [TypeConverter(typeof(ExpandableObjectConverter))] public partial class CellInt { public override string ToString() => Value.ToString(); } diff --git a/pkNX.Structures.FlatBuffers.SWSH/Gen8/Other/PokeResourceTable.cs b/pkNX.Structures.FlatBuffers.SWSH/Gen8/Other/PokeResourceTable.cs index 54ec604e..02fd6636 100644 --- a/pkNX.Structures.FlatBuffers.SWSH/Gen8/Other/PokeResourceTable.cs +++ b/pkNX.Structures.FlatBuffers.SWSH/Gen8/Other/PokeResourceTable.cs @@ -10,6 +10,6 @@ namespace pkNX.Structures.FlatBuffers.SWSH; // poke_resource_table.gfbpmcatalog -/// for Sword/Shield +/// for Sword/Shield [TypeConverter(typeof(ExpandableObjectConverter))] -public partial class Gfbpmcatalog { } +partial class GFBpmcatalog { } diff --git a/pkNX.Structures.FlatBuffers.SWSH/Gen8/Other/ShopInventory.cs b/pkNX.Structures.FlatBuffers.SWSH/Gen8/Other/ShopInventory.cs new file mode 100644 index 00000000..6bc4f9a8 --- /dev/null +++ b/pkNX.Structures.FlatBuffers.SWSH/Gen8/Other/ShopInventory.cs @@ -0,0 +1,130 @@ +using System.ComponentModel; + +// ReSharper disable UnusedType.Global +// ReSharper disable UnusedMember.Global +#nullable disable + +namespace pkNX.Structures.FlatBuffers.SWSH; + +[TypeConverter(typeof(ExpandableObjectConverter))] +public partial class ShopInventory { } + +[TypeConverter(typeof(ExpandableObjectConverter))] +public partial class SingleShop +{ + public override string ToString() => $"{Hash:X16} - {Inventories}"; + + public static readonly Dictionary SWSH = new() + { + // Galar + { 0x1F3FF031A3A24490, "Poké Mart [0 Badges, Before Catching Tutorial]" }, + { 0x8E308F85B43038B4, "Motostoke [Upper Tier, TMs]" }, + { 0x8E309085B4303A67, "Hammerlocke [West, TMs]" }, + { 0x8E309185B4303C1A, "Hammerlocke [East, TMs]" }, + { 0x8E309285B4303DCD, "Wyndon [North, TMs]" }, + { 0x8E308B85B43031E8, "Battle Tower [TMs]" }, + { 0xCBD67969D873539B, "Motostoke [Lower Tier, Miscellaneous]" }, + { 0xCBD67869D87351E8, "Hammerlocke [South, Miscellaneous]" }, + { 0xCBD669D8735701, "Wyndon [South, Miscellaneous]" }, + { 0x04D7046DA09D3C78, "Hulbury [Herb Shop]" }, + { 0x4B2F9E98DDCB0707, "Hulbury [Incense Shop]" }, + { 0xE379CDF67A297070, "Wedgehurst [Berry Shop]" }, + { 0x3FD7A44219BF30BB, "Hammerlocke [South, BP Shop]" }, + { 0x3FD7A34219BF2F08, "Battle Tower [Battle Items]" }, + { 0x3FD7A64219BF3421, "Battle Tower [Nature Mints]" }, + // 0xD1BEA92EAAE52B5A -- Wishing Piece + X Items... unused? + + // Wild Area + // next 84 tables are all Ingredient Sellers with similar inventories that rotate daily; don't bother labeling (why hardcode everything GF?) + { 0xD1BEAA2EAAE52D0D, "Watt Trader 1 [Net Ball]" }, + { 0xD1BEA72EAAE527F4, "Watt Trader 1 [Dive Ball]" }, + { 0xD1BEA82EAAE529A7, "Watt Trader 1 [Nest Ball]" }, + { 0xD1BEA52EAAE5248E, "Watt Trader 1 [Repeat Ball]" }, + { 0xD1BEA62EAAE52641, "Watt Trader 1 [Timer Ball]" }, + { 0xD1BEA32EAAE52128, "Watt Trader 1 [Luxury Ball]" }, + { 0xD1BEA42EAAE522DB, "Watt Trader 1 [Dusk Ball]" }, + { 0xD1BEA12EAAE51DC2, "Watt Trader 1 [Heal Ball]" }, + { 0xD1BEA22EAAE51F75, "Watt Trader 1 [Quick Ball]" }, + + { 0xD1C20F2EAAE80E83, "Watt Trader 2 [Net Ball]" }, + { 0xD1C20E2EAAE80CD0, "Watt Trader 2 [Dive Ball]" }, + { 0xD1C2112EAAE811E9, "Watt Trader 2 [Nest Ball]" }, + { 0xD1C2102EAAE81036, "Watt Trader 2 [Repeat Ball]" }, + { 0xD1C2132EAAE8154F, "Watt Trader 2 [Timer Ball]" }, + { 0xD1C2122EAAE8139C, "Watt Trader 2 [Luxury Ball]" }, + { 0xD1C2152EAAE818B5, "Watt Trader 2 [Dusk Ball]" }, + { 0xD1C2142EAAE81702, "Watt Trader 2 [Heal Ball]" }, + { 0xD1C2172EAAE81C1B, "Watt Trader 2 [Quick Ball]" }, + + { 0xD1C2162EAAE81A68, "Watt Trader 3 [Net Ball]" }, + { 0xD1B79D2EAADEF848, "Watt Trader 3 [Dive Ball]" }, + { 0xD1B79E2EAADEF9FB, "Watt Trader 3 [Nest Ball]" }, + { 0xD1B79F2EAADEFBAE, "Watt Trader 3 [Repeat Ball]" }, + { 0xD1B7A02EAADEFD61, "Watt Trader 3 [Timer Ball]" }, + { 0xD1B7A12EAADEFF14, "Watt Trader 3 [Luxury Ball]" }, + { 0xD1B7A22EAADF00C7, "Watt Trader 3 [Dusk Ball]" }, + { 0xD1B7A32EAADF027A, "Watt Trader 3 [Heal Ball]" }, + { 0xD1B7A42EAADF042D, "Watt Trader 3 [Quick Ball]" }, + + { 0xD1B7952EAADEEAB0, "Watt Trader 4 [Net Ball]" }, + { 0xD1B7962EAADEEC63, "Watt Trader 4 [Dive Ball]" }, + { 0xD1BB232EAAE211D1, "Watt Trader 4 [Nest Ball]" }, + { 0xD1BB222EAAE2101E, "Watt Trader 4 [Repeat Ball]" }, + { 0xD1BB212EAAE20E6B, "Watt Trader 4 [Timer Ball]" }, + { 0xD1BB202EAAE20CB8, "Watt Trader 4 [Luxury Ball]" }, + { 0xD1BB272EAAE2189D, "Watt Trader 4 [Dusk Ball]" }, + { 0xD1BB262EAAE216EA, "Watt Trader 4 [Heal Ball]" }, + { 0xD1BB252EAAE21537, "Watt Trader 4 [Quick Ball]" }, + + { 0xD1BB242EAAE21384, "Watt Trader 5 [Net Ball]" }, + { 0xD1BB1B2EAAE20439, "Watt Trader 5 [Dive Ball]" }, + { 0xD1BB1A2EAAE20286, "Watt Trader 5 [Nest Ball]" }, + { 0xD1CC212EAAF0819E, "Watt Trader 5 [Repeat Ball]" }, + { 0xD1CC222EAAF08351, "Watt Trader 5 [Timer Ball]" }, + { 0xD1CC1F2EAAF07E38, "Watt Trader 5 [Luxury Ball]" }, + { 0xD1CC202EAAF07FEB, "Watt Trader 5 [Dusk Ball]" }, + { 0xD1CC252EAAF0886A, "Watt Trader 5 [Heal Ball]" }, + { 0xD1CC262EAAF08A1D, "Watt Trader 5 [Quick Ball]" }, + + { 0xD1CC232EAAF08504, "Watt Trader 6 [Net Ball]" }, + { 0xD1CC242EAAF086B7, "Watt Trader 6 [Dive Ball]" }, + { 0xD1CC192EAAF07406, "Watt Trader 6 [Repeat Ball]" }, + { 0xD1CC1A2EAAF075B9, "Watt Trader 6 [Quick Ball]" }, + { 0xD1CFA72EAAF39B27, "Watt Trader 6 [Heal Ball]" }, + + // Isle of Armor + { 0x5870C0165650F6A5, "Fields of Honor [Berry Shop]" }, + + // Crown Tundra + { 0x81DA6390A03C7E3F, "Freezington [Peddler]" }, + { 0x813C350B0B777943, "Snowslide Slope [Today's Highlight, TR00-TR09]" }, + { 0x813C360B0B777AF6, "Snowslide Slope [Today's Highlight, TR10-TR19]" }, + { 0x813C370B0B777CA9, "Snowslide Slope [Today's Highlight, TR20-TR29]" }, + { 0x813C380B0B777E5C, "Snowslide Slope [Today's Highlight, TR30-TR39]" }, + { 0x813C390B0B77800F, "Snowslide Slope [Today's Highlight, TR40-TR49]" }, + { 0x813C3A0B0B7781C2, "Snowslide Slope [Today's Highlight, TR50-TR59]" }, + { 0x813C3B0B0B778375, "Snowslide Slope [Today's Highlight, TR60-TR69]" }, + { 0x813C3C0B0B778528, "Snowslide Slope [Today's Highlight, TR70-TR79]" }, + { 0x813C3D0B0B7786DB, "Snowslide Slope [Today's Highlight, TR80-TR89]" }, + { 0x813F3A0B0B79B799, "Snowslide Slope [Today's Highlight, TR90-TR99]" }, + { 0xF49C86F8683842BF, "Max Lair [Dynite Ore Trader]" }, + }; +} + +[TypeConverter(typeof(ExpandableObjectConverter))] +public partial class MultiShop +{ + public override string ToString() => $"{Hash:X16} - {string.Join(", ", Inventories.Select(z => z.ToString()))}"; + + public static readonly Dictionary SWSH = new() + { + { 0x66CA73B2966BB871, "Poké Mart Inventories [0-8 Badges]" }, + { 0x5870BD165650F18C, "Fields of Honor [Watt Trader, 0-8 Badges]" }, + }; +} + +[TypeConverter(typeof(ExpandableObjectConverter))] +public partial class Inventory +{ + public override string ToString() => $"{string.Join(",", Items.Select(z => z.ToString()))}"; +} diff --git a/pkNX.Structures/ArrayUtil.cs b/pkNX.Structures/ArrayUtil.cs index 1c424278..ccf6df06 100644 --- a/pkNX.Structures/ArrayUtil.cs +++ b/pkNX.Structures/ArrayUtil.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; namespace pkNX.Structures; @@ -16,14 +15,6 @@ public static byte[] Slice(this byte[] src, int offset, int length) return data; } - public static byte[] SliceEnd(this byte[] src, int offset) - { - int length = src.Length - offset; - byte[] data = new byte[length]; - Buffer.BlockCopy(src, offset, data, 0, data.Length); - return data; - } - public static T[] Slice(this T[] src, int offset, int length) { var data = new T[length]; @@ -31,14 +22,6 @@ public static T[] Slice(this T[] src, int offset, int length) return data; } - public static T[] SliceEnd(this T[] src, int offset) - { - int length = src.Length - offset; - var data = new T[length]; - Array.Copy(src, offset, data, 0, data.Length); - return data; - } - public static bool WithinRange(int value, int min, int max) => min <= value && value < max; public static T[][] Split(this T[] data, int size) @@ -49,73 +32,6 @@ public static T[][] Split(this T[] data, int size) return result; } - public static IEnumerable EnumerateSplit(T[] bin, int size, int start = 0) - { - for (int i = start; i < bin.Length; i += size) - yield return bin.Slice(i, size); - } - - public static IEnumerable EnumerateSplit(T[] bin, int size, int start, int end) - { - if (end < 0) - end = bin.Length; - for (int i = start; i < end; i += size) - yield return bin.Slice(i, size); - } - - public static bool[] GitBitFlagArray(byte[] data, int offset, int count) - { - bool[] result = new bool[count]; - for (int i = 0; i < result.Length; i++) - result[i] = (data[offset + (i >> 3)] >> (i & 7) & 0x1) == 1; - return result; - } - - public static void SetBitFlagArray(byte[] data, int offset, bool[] value) - { - for (int i = 0; i < value.Length; i++) - { - var ofs = offset + (i >> 3); - var mask = (1 << (i & 7)); - if (value[i]) - data[ofs] |= (byte)mask; - else - data[ofs] &= (byte)~mask; - } - } - - public static byte[] SetBitFlagArray(bool[] value) - { - byte[] data = new byte[value.Length / 8]; - SetBitFlagArray(data, 0, value); - return data; - } - - /// - /// Copies a list to the destination list, with an option to copy to a starting point. - /// - /// Source list to copy from - /// Destination list/array - /// Criteria for skipping a slot - /// Starting point to copy to - /// Count of copied. - public static int CopyTo(this IEnumerable list, IList dest, Func skip, int start = 0) - { - int ctr = start; - int skipped = 0; - foreach (var z in list) - { - // seek forward to next open slot - int next = FindNextValidIndex(dest, skip, ctr); - if (next == -1) - break; - skipped += next - ctr; - ctr = next; - dest[ctr++] = z; - } - return ctr - start - skipped; - } - public static int FindNextValidIndex(IList dest, Func skip, int ctr) { while (true) @@ -129,26 +45,6 @@ public static int FindNextValidIndex(IList dest, Func skip, int c } } - /// - /// Copies an list to the destination list, with an option to copy to a starting point. - /// - /// Typed object to copy - /// Source list to copy from - /// Destination list/array - /// Starting point to copy to - /// Count of copied. - public static int CopyTo(this IEnumerable list, IList dest, int start = 0) - { - int ctr = start; - foreach (var z in list) - { - if ((uint)ctr >= dest.Count) - break; - dest[ctr++] = z; - } - return ctr - start; - } - internal static T[] ConcatAll(params T[][] arr) { int len = 0; @@ -185,31 +81,6 @@ internal static T[] ConcatAll(T[] arr1, T[] arr2, T[] arr3) arr3.CopyTo(result, arr1.Length + arr2.Length); return result; } - - internal static T[] ConcatAll(T[] arr1, T[] arr2, ReadOnlySpan arr3) - { - int len = arr1.Length + arr2.Length + arr3.Length; - var result = new T[len]; - arr1.CopyTo(result, 0); - arr2.CopyTo(result, arr1.Length); - arr3.CopyTo(result.AsSpan(arr1.Length + arr2.Length)); - return result; - } -} - -public static class ArrayUtilsExt -{ - public static TSource[] Append(this TSource[] first, TSource second, params TSource[] third) - { - return ArrayUtil.ConcatAll(first, new[] { second }, third); - } - - public static TSource[] Remove(this TSource[] first, TSource toRemove) - { - var list = first.ToList(); - list.Remove(toRemove); - return list.ToArray(); - } } public static class FlagUtil diff --git a/pkNX.Structures/Havok/HavokCollision.cs b/pkNX.Structures/Havok/HavokCollision.cs index 47bd6ae5..6f76f707 100644 --- a/pkNX.Structures/Havok/HavokCollision.cs +++ b/pkNX.Structures/Havok/HavokCollision.cs @@ -6,6 +6,9 @@ namespace pkNX.Structures; +/// +/// Collision data for a map, used by Scarlet / Violet. +/// public static class HavokCollision { public static AABBTree ParseAABBTree(ReadOnlySpan trcol) diff --git a/pkNX.Tests/UnitTest1.cs b/pkNX.Tests/UnitTest1.cs index b0740327..e6026de7 100644 --- a/pkNX.Tests/UnitTest1.cs +++ b/pkNX.Tests/UnitTest1.cs @@ -6,8 +6,5 @@ namespace pkNX.Tests; public class UnitTest1 { [Fact] - public void TestMethod1() - { - true.Should().BeTrue(); - } + public void TestMethod1() => true.Should().BeTrue(); } diff --git a/pkNX.Tests/VFS/FileSystems/ZipArchiveFSTest.cs b/pkNX.Tests/VFS/FileSystems/ZipArchiveFSTest.cs index 313e0604..4ea394ed 100644 --- a/pkNX.Tests/VFS/FileSystems/ZipArchiveFSTest.cs +++ b/pkNX.Tests/VFS/FileSystems/ZipArchiveFSTest.cs @@ -1,24 +1,22 @@ using System; using System.IO; -using System.Linq; using System.Text; using System.IO.Compression; using pkNX.Containers.VFS; using Xunit; +using FluentAssertions; namespace pkNX.Tests; -public class ZipArchiveFSTest +public class ZipArchiveFSTest : IDisposable { - private Stream zipStream; - private ZipArchiveFileSystem fileSystem; - private string fileContentString = "this is a file"; + private readonly Stream zipStream = new MemoryStream(); + private readonly ZipArchiveFileSystem fileSystem; + private const string fileContentString = "this is a file"; //setup public ZipArchiveFSTest() { - zipStream = new MemoryStream(); - var fileContentBytes = Encoding.ASCII.GetBytes(fileContentString); using (var zipOutput = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) @@ -50,71 +48,76 @@ public void Dispose() [Fact] public void GetEntitiesOfRootTest() { - Assert.Equal(new[] + var expect = new[] { - textfileAPath, - directoryPath, - scratchDirectoryPath - }, fileSystem.GetEntitiesInDirectory(FileSystemPath.Root).ToArray()); + textfileAPath, + directoryPath, + scratchDirectoryPath, + }; + expect.Should().Contain(fileSystem.GetEntitiesInDirectory(FileSystemPath.Root)); } [Fact] public void GetEntitiesOfDirectoryTest() { - Assert.Equal(new[] + var expect = new[] { - fileInDirectoryPath - }, fileSystem.GetEntitiesInDirectory(directoryPath).ToArray()); + fileInDirectoryPath, + }; + expect.Should().Contain(fileSystem.GetEntitiesInDirectory(directoryPath)); } [Fact] public void ExistsTest() { - Assert.True(fileSystem.Exists(FileSystemPath.Root)); - Assert.True(fileSystem.Exists(textfileAPath)); - Assert.True(fileSystem.Exists(directoryPath)); - Assert.True(fileSystem.Exists(fileInDirectoryPath)); - Assert.False(fileSystem.Exists(FileSystemPath.Parse("/nonExistingFile"))); - Assert.False(fileSystem.Exists(FileSystemPath.Parse("/nonExistingDirectory/"))); - Assert.False(fileSystem.Exists(FileSystemPath.Parse("/directory/nonExistingFileInDirectory"))); + fileSystem.Exists(FileSystemPath.Root).Should().BeTrue(); + fileSystem.Exists(textfileAPath).Should().BeTrue(); + fileSystem.Exists(directoryPath).Should().BeTrue(); + fileSystem.Exists(fileInDirectoryPath).Should().BeTrue(); + fileSystem.Exists(FileSystemPath.Parse("/nonExistingFile")).Should().BeFalse(); + fileSystem.Exists(FileSystemPath.Parse("/nonExistingDirectory/")).Should().BeFalse(); + fileSystem.Exists(FileSystemPath.Parse("/directory/nonExistingFileInDirectory")).Should().BeFalse(); } [Fact] public void CanReadFile() { - var file = fileSystem.OpenFile(textfileAPath, FileMode.Open, FileAccess.ReadWrite); + using var file = fileSystem.OpenFile(textfileAPath, FileMode.Open, FileAccess.ReadWrite); var text = file.ReadAllText(); - Assert.True(string.Equals(text, fileContentString)); + text.Should().Be(fileContentString); } [Fact] public void CanWriteFile() { - var file = fileSystem.OpenFile(textfileAPath, FileMode.Open, FileAccess.ReadWrite); - var textBytes = Encoding.ASCII.GetBytes(fileContentString + " and a new string"); - file.Write(textBytes); - file.Close(); - - - file = fileSystem.OpenFile(textfileAPath, FileMode.Open, FileAccess.ReadWrite); - var text = file.ReadAllText(); - Assert.True(string.Equals(text, fileContentString + " and a new string")); + const string reviseTo = fileContentString + " and a new string"; + { + using var file = fileSystem.OpenFile(textfileAPath, FileMode.Open, FileAccess.ReadWrite); + var textBytes = Encoding.ASCII.GetBytes(reviseTo); + file.Write(textBytes); + } + { + using var file = fileSystem.OpenFile(textfileAPath, FileMode.Open, FileAccess.ReadWrite); + var text = file.ReadAllText(); + text.Should().Be(reviseTo); + } } [Fact] public void CanAddFile() { var fsp = FileSystemPath.Parse("/scratchdirectory/recentlyadded.txt"); - var file = fileSystem.CreateFile(fsp); - var textBytes = "recently added"u8.ToArray(); - file.Write(textBytes); - file.Close(); - - Assert.True(fileSystem.Exists(fsp)); - - file = fileSystem.OpenFile(fsp, FileMode.Open, FileAccess.ReadWrite); - var text = file.ReadAllText(); - Assert.True(string.Equals(text, "recently added")); + { + using var file = fileSystem.CreateFile(fsp); + var textBytes = "recently added"u8; + file.Write(textBytes); + } + fileSystem.Exists(fsp).Should().BeTrue(); + { + using var sameFile = fileSystem.OpenFile(fsp, FileMode.Open, FileAccess.ReadWrite); + var text = sameFile.ReadAllText(); + text.Should().Be("recently added"); + } } [Fact] @@ -122,7 +125,6 @@ public void CanAddDirectory() { var fsp = FileSystemPath.Parse("/scratchdirectory/dir/"); fileSystem.CreateDirectory(fsp); - - Assert.True(fileSystem.Exists(fsp)); + fileSystem.Exists(fsp).Should().BeTrue(); } } diff --git a/pkNX.WinForms/Dumping/GameDumperPLA.cs b/pkNX.WinForms/Dumping/GameDumperPLA.cs index 693b33ff..5a00818c 100644 --- a/pkNX.WinForms/Dumping/GameDumperPLA.cs +++ b/pkNX.WinForms/Dumping/GameDumperPLA.cs @@ -73,7 +73,7 @@ public void DumpPokeInfo() var s = ROM.GetStrings(TextName.SpeciesNames); var lrd = ROM.GetFile(GameFile.Learnsets)[0]; - var lr = FlatBufferConverter.DeserializeFrom(lrd); + var lr = FlatBufferConverter.DeserializeFrom(lrd); var evd = ROM.GetFile(GameFile.Evolutions)[0]; var ev = FlatBufferConverter.DeserializeFrom(evd); var pt = new PersonalTable8LA(ROM.GetFile(GameFile.PersonalStats)); @@ -145,7 +145,7 @@ private void DumpMoveUsers(IPersonalTable pt, Learnset lr) File.WriteAllLines(outname, Users); } - private static string GetSpeciesMove(string[] spec, LearnsetMeta x, int move) + private static string GetSpeciesMove(ReadOnlySpan spec, LearnsetMeta x, int move) { var learnset = x.Arceus.FirstOrDefault(w => w.Move == move); var level = learnset is null ? "INVALID" : learnset.Level.ToString(); @@ -433,7 +433,7 @@ public void DumpWilds() const float bias = 20; var hexBin = new List(); - var allSlots = new List(); + var allSlots = new List(); var allSpawners = new List(); var allWormholes = new List(); var allLocations = new List(); diff --git a/pkNX.WinForms/Dumping/MassOutbreakRipper.cs b/pkNX.WinForms/Dumping/MassOutbreakRipper.cs index 29c88f3a..8245ff6c 100644 --- a/pkNX.WinForms/Dumping/MassOutbreakRipper.cs +++ b/pkNX.WinForms/Dumping/MassOutbreakRipper.cs @@ -40,8 +40,6 @@ private sealed record PickledOutbreak public required byte Form { get; init; } public byte Gender { get; init; } = 0xFF; - public required byte LevelMin { get; init; } - public required byte LevelMax { get; init; } public required RibbonIndex Ribbon { get; init; } public required byte MetBase { get; init; } @@ -65,10 +63,10 @@ private static void DumpDeliveryOutbreakData(IFileInternal ROM, string path) if (!File.Exists(zoneF2)) // temporary workaround until DLC 2 zoneF2 = zoneF1; - var dataZoneF0 = GetDistributionContents(zoneF0, out int indexZoneF0); - var dataZoneF1 = GetDistributionContents(Path.Combine(path, zoneF1), out int indexZoneF1); - var dataZoneF2 = GetDistributionContents(Path.Combine(path, zoneF2), out int indexZoneF2); - var dataPokeData = GetDistributionContents(Path.Combine(path, pokedata), out int indexPokeData); + var dataZoneF0 = GetDistributionContents(zoneF0); + var dataZoneF1 = GetDistributionContents(Path.Combine(path, zoneF1)); + var dataZoneF2 = GetDistributionContents(Path.Combine(path, zoneF2)); + var dataPokeData = GetDistributionContents(Path.Combine(path, pokedata)); var tableZoneF0 = FlatBufferConverter.DeserializeFrom(dataZoneF0); var tableZoneF1 = FlatBufferConverter.DeserializeFrom(dataZoneF1); @@ -76,7 +74,7 @@ private static void DumpDeliveryOutbreakData(IFileInternal ROM, string path) var tablePokeData = FlatBufferConverter.DeserializeFrom(dataPokeData); var dirDistText = Path.Combine(path, "parse"); - ExportParse(ROM, dirDistText, tableZoneF0, tableZoneF1, tableZoneF2, tablePokeData); + ExportParse(dirDistText, tableZoneF0, tableZoneF1, tableZoneF2, tablePokeData); AddToPickleJar(ROM, tableZoneF0, tableZoneF1, tableZoneF2, tablePokeData); DumpPretty(ROM, dirDistText); @@ -253,7 +251,7 @@ private static void ConsolidateMetInfo(IEnumerable encs) private record struct LevelRange(byte Min, byte Max); - private static void AddToJar(CachedOutbreak[] encs) + private static void AddToJar(IEnumerable encs) { foreach (var enc in encs) { @@ -275,8 +273,6 @@ private static void AddToJar(CachedOutbreak[] encs) SexType.FEMALE => 1, _ => throw new ArgumentOutOfRangeException(nameof(SexType), pk.Sex, "Unknown Gender"), }, - LevelMin = (byte)pk.MinLevel, - LevelMax = (byte)pk.MaxLevel, Ribbon = unchecked((RibbonIndex)(pk.AddRibbonPercentage == 0 ? -1 : (int)pk.AddRibbonType - 1)), ForceScaleRange = pk.EnableScaleRange, @@ -375,24 +371,7 @@ void TryAdd(ulong ID, short rate) return ret.ToArray(); } - private static byte[] GetDistributionContents(string path, out int index) - { - index = 0; // todo - return File.ReadAllBytes(path); - } - - private static string Humanize(OutbreakEnableTable enable) - { - var sb = new StringBuilder(); - if (enable.Air1) sb.Append(" Air1"); - if (enable.Air2) sb.Append(" Air2"); - if (enable.Land) sb.Append(" Land"); - if (enable.UpWater) sb.Append(" UpWater"); - if (enable.UnderWater) sb.Append(" Underwater"); - if (sb.Length == 0) - return "Enable: Unrestricted"; - return "Enable:" + sb; - } + private static byte[] GetDistributionContents(string path) => File.ReadAllBytes(path); private static string Humanize(EnableTable enable) { @@ -415,11 +394,11 @@ private static string Humanize(EnableTable enable) _ => "Version: None", }; - private static void ExportParse(IFileInternal ROM, string dir, DeliveryOutbreakArray tableZoneF0, DeliveryOutbreakArray tableZoneF1, DeliveryOutbreakArray tableZoneF2, DeliveryOutbreakPokeDataArray tablePokeData) + private static void ExportParse(string dir, DeliveryOutbreakArray tableZoneF0, DeliveryOutbreakArray tableZoneF1, DeliveryOutbreakArray tableZoneF2, DeliveryOutbreakPokeDataArray tablePokeData) { var dumpZ0 = TableUtil.GetTable(tableZoneF0.Table); var dumpZ1 = TableUtil.GetTable(tableZoneF1.Table); - var dumpZ2 = TableUtil.GetTable(tableZoneF2.Table); + //var dumpZ2 = TableUtil.GetTable(tableZoneF2.Table); var dumpPD = TableUtil.GetTable(tablePokeData.Table); var dump = new[] { @@ -466,12 +445,12 @@ private static void DumpPretty(IFileInternal ROM, string dir) { var parent = enc.Parent; WriteParent(ROM, sw, parent); - WriteLocationList(sw, parent.MetInfo, parent.MetBase, enc.LevelMin, enc.LevelMax); + WriteLocationList(sw, parent.MetInfo, parent.MetBase); sw.WriteLine(); } } - private static void WriteLocationList(TextWriter sw, Dictionary metFlags, byte baseMet, byte min, byte max) + private static void WriteLocationList(TextWriter sw, Dictionary metFlags, byte baseMet) { foreach ((var range, UInt128 flags) in metFlags.OrderBy(z => z.Key.Min).ThenBy(z => z.Key.Max)) { @@ -496,10 +475,11 @@ private static void WriteParent(IFileInternal ROM, StreamWriter sw, CachedOutbre var species = GetCommonText(ROM, "monsname", lang, cfg); var ribbons = GetCommonText(ROM, "ribbon", lang, cfg); - var form = GetFormName(ROM, (ushort)parent.Poke.DevId, (byte)parent.Poke.FormId) switch + var formName = TeraRaidRipper.GetFormName(ROM, (ushort)enc.DevId, (byte)enc.FormId); + var form = formName switch { - not "" when enc.FormId is 0 => $" ({GetFormName(ROM, (ushort)enc.DevId, (byte)enc.FormId)})", - not "" => $"-{enc.FormId} ({GetFormName(ROM, (ushort)enc.DevId, (byte)enc.FormId)})", + not "" when enc.FormId is 0 => $" ({formName})", + not "" => $"-{enc.FormId} ({formName})", _ => string.Empty, }; @@ -517,49 +497,4 @@ private static void WriteParent(IFileInternal ROM, StreamWriter sw, CachedOutbre if (enc.AddRibbonPercentage != 0) sw.WriteLine($"Ribbon/Mark: {ribbons[(int)enc.AddRibbonType - 1]} ({enc.AddRibbonPercentage}%)"); } - - private static string GetFormName(IFileInternal ROM, ushort species, byte form) - { - const string lang = "English"; - var cfg = new TextConfig(Structures.GameVersion.SV); - var text = GetCommonText(ROM, "zkn_form", lang, cfg); - var abil = GetCommonText(ROM, "tokusei", lang, cfg); - var type = GetCommonText(ROM, "typename", lang, cfg); - var path = ROM.GetPackedFile("message/dat/English/common/zkn_form.tbl"); - var ahtb = new AHTB(path); - - var GenericFormNames = new HashSet() { Tauros, Unown, Kyogre, Groudon, Rotom, Arceus, Kyurem, Greninja, Rockruff }; - string[] TaurosForms = new[] { "", "Combat Breed", "Blaze Breed", "Aqua Breed" }; - char[] UnownForms = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!?".ToCharArray(); - for (int i = 0; i < text.Length; i++) - { - var entry = ahtb.Entries[i]; - var name = entry.Name; - var line = text[i]; - - // some species have form strings that are just the species name (Rotom), or are not descriptive (e.g. Unown "One form"), or no form string at all! - if (GenericFormNames.Contains((Structures.Species)species)) - { - return (Structures.Species)species switch - { - Tauros when form is not 0 => $"Paldean Form / {TaurosForms[form]}", - Unown => $"Unown {UnownForms[form]}", // A-Z!? - Kyogre or Groudon when form is 0 => "", // Kyogre-0 / Groudon-0 - Rotom when form is 0 => "", // Rotom-0 - Arceus => $"{type[form]}", // Types - Kyurem when form is 0 => "", // Kyurem-0 - Greninja when form is 1 => $"{abil[210]}", // Battle Bond Greninja - Rockruff when form is 1 => $"{abil[020]}", // Own Tempo Rockruff - _ => "", - }; - } - - else if (name == $"ZKN_FORM_{species:000}_{form:000}") - { - return line; - } - } - - return ""; - } } diff --git a/pkNX.WinForms/Dumping/TeraRaidRipper.cs b/pkNX.WinForms/Dumping/TeraRaidRipper.cs index 90c5a68d..f5df8cab 100644 --- a/pkNX.WinForms/Dumping/TeraRaidRipper.cs +++ b/pkNX.WinForms/Dumping/TeraRaidRipper.cs @@ -1,7 +1,6 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using pkNX.Containers; @@ -162,7 +161,6 @@ private static void DumpDistributionRaids(IFileInternal ROM, string path, List(dataEncounters); var tableDrops = FlatBufferConverter.DeserializeFrom(dataDrop); @@ -378,11 +371,7 @@ private static void DumpJson(object flat, string dir, string name) File.WriteAllText(Path.Combine(dir, fileName), json); } - private static byte[] GetDistributionContents(string path, out int index) - { - index = 0; // todo - return File.ReadAllBytes(path); - } + private static byte[] GetDistributionContents(string path) => File.ReadAllBytes(path); private static string[] GetCommonText(IFileInternal ROM, string name, string lang, TextConfig cfg) { @@ -481,10 +470,11 @@ private static void DumpPretty(IFileInternal ROM, DeliveryRaidEnemyTableArray ta _ => string.Empty, // Default }; - var form = GetFormName(ROM, (ushort)boss.DevId, (byte)boss.FormId) switch + var formName = GetFormName(ROM, (ushort)boss.DevId, (byte)boss.FormId); + var form = formName switch { - not "" when boss.FormId is 0 => $" ({GetFormName(ROM, (ushort)boss.DevId, (byte)boss.FormId)})", - not "" => $"-{boss.FormId} ({GetFormName(ROM, (ushort)boss.DevId, (byte)boss.FormId)})", + not "" when boss.FormId is 0 => $" ({formName})", + not "" => $"-{boss.FormId} ({formName})", _ => string.Empty, }; @@ -623,7 +613,7 @@ private static void DumpPretty(IFileInternal ROM, DeliveryRaidEnemyTableArray ta File.WriteAllLines(Path.Combine(dir, $"pretty_{ident}.txt"), lines); } - private static string GetFormName(IFileInternal ROM, ushort species, byte form) + public static string GetFormName(IFileInternal ROM, ushort species, byte form) { const string lang = "English"; var cfg = new TextConfig(GameVersion.SV); @@ -632,9 +622,9 @@ private static string GetFormName(IFileInternal ROM, ushort species, byte form) var path = ROM.GetPackedFile("message/dat/English/common/zkn_form.tbl"); var ahtb = new AHTB(path); - var GenericFormNames = new HashSet() { Tauros, Unown, Kyogre, Groudon, Rotom, Arceus, Kyurem, Greninja, Rockruff }; - string[] TaurosForms = new[] { "", "Combat Breed", "Blaze Breed", "Aqua Breed" }; - char[] UnownForms = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!?".ToCharArray(); + var GenericFormNames = new HashSet { Tauros, Unown, Kyogre, Groudon, Rotom, Arceus, Kyurem, Greninja, Rockruff }; + string[] TaurosForms = { "", "Combat Breed", "Blaze Breed", "Aqua Breed" }; + ReadOnlySpan UnownForms = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!?"; for (int i = 0; i < text.Length; i++) { var entry = ahtb.Entries[i]; @@ -657,13 +647,9 @@ private static string GetFormName(IFileInternal ROM, ushort species, byte form) _ => "", }; } - - else if (name == $"ZKN_FORM_{species:000}_{form:000}") - { + if (name == $"ZKN_FORM_{species:000}_{form:000}") return line; - } } - return ""; } diff --git a/pkNX.WinForms/MainEditor/EditorGG.cs b/pkNX.WinForms/MainEditor/EditorGG.cs index 14b0304a..1375d1f4 100644 --- a/pkNX.WinForms/MainEditor/EditorGG.cs +++ b/pkNX.WinForms/MainEditor/EditorGG.cs @@ -335,7 +335,7 @@ private void EditShop(bool shop2) if (!shop2) { var table = shop.Single; - var names = table.Select((z, _) => $"{(z.LGPE.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); + var names = table.Select((z, _) => $"{(SingleShop.LGPE.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); var cache = new DirectCache(table); using var form = new GenericEditor(cache, names, $"{nameof(SingleShop)} Editor", Randomize); form.ShowDialog(); @@ -359,7 +359,7 @@ void Randomize() else { var table = shop.Multi; - var names = table.Select((z, _) => $"{(z.LGPE.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); + var names = table.Select((z, _) => $"{(MultiShop.LGPE.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); var cache = new DirectCache(table); using var form = new GenericEditor(cache, names, $"{nameof(MultiShop)} Editor", Randomize); form.ShowDialog(); diff --git a/pkNX.WinForms/MainEditor/EditorSWSH.cs b/pkNX.WinForms/MainEditor/EditorSWSH.cs index 89734795..c6facea2 100644 --- a/pkNX.WinForms/MainEditor/EditorSWSH.cs +++ b/pkNX.WinForms/MainEditor/EditorSWSH.cs @@ -423,7 +423,7 @@ private void EditShop(bool shop2) if (!shop2) { var table = shop.Single; - var names = table.Select((z, _) => $"{(ShopSWSH.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); + var names = table.Select((z, _) => $"{(SingleShop.SWSH.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); var cache = new DirectCache(table); using var form = new GenericEditor(cache, names, $"{nameof(SingleShop)} Editor", Randomize); form.ShowDialog(); @@ -450,7 +450,7 @@ void Randomize() else { var table = shop.Multi; - var names = table.Select((z, _) => $"{(ShopSWSH.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); + var names = table.Select((z, _) => $"{(SingleShop.SWSH.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); var cache = new DirectCache(table); using var form = new GenericEditor(cache, names, $"{nameof(MultiShop)} Editor", Randomize); form.ShowDialog(); @@ -476,103 +476,6 @@ void Randomize() arc[0] = shop.SerializeFrom(); } - - public readonly Dictionary ShopSWSH = new() - { - // Galar - { 0x1F3FF031A3A24490, "Poké Mart [0 Badges, Before Catching Tutorial]" }, - { 0x8E308F85B43038B4, "Motostoke [Upper Tier, TMs]" }, - { 0x8E309085B4303A67, "Hammerlocke [West, TMs]" }, - { 0x8E309185B4303C1A, "Hammerlocke [East, TMs]" }, - { 0x8E309285B4303DCD, "Wyndon [North, TMs]" }, - { 0x8E308B85B43031E8, "Battle Tower [TMs]" }, - { 0xCBD67969D873539B, "Motostoke [Lower Tier, Miscellaneous]" }, - { 0xCBD67869D87351E8, "Hammerlocke [South, Miscellaneous]" }, - { 0xCBD67B69D8735701, "Wyndon [South, Miscellaneous]" }, - { 0x04D7046DA09D3C78, "Hulbury [Herb Shop]" }, - { 0x4B2F9E98DDCB0707, "Hulbury [Incense Shop]" }, - { 0xE379CDF67A297070, "Wedgehurst [Berry Shop]" }, - { 0x3FD7A44219BF30BB, "Hammerlocke [South, BP Shop]" }, - { 0x3FD7A34219BF2F08, "Battle Tower [Battle Items]" }, - { 0x3FD7A64219BF3421, "Battle Tower [Nature Mints]" }, - // 0xD1BEA92EAAE52B5A -- Wishing Piece + X Items... unused? - - // Wild Area - // next 84 tables are all Ingredient Sellers with similar inventories that rotate daily; don't bother labeling (why hardcode everything GF?) - { 0xD1BEAA2EAAE52D0D, "Watt Trader 1 [Net Ball]" }, - { 0xD1BEA72EAAE527F4, "Watt Trader 1 [Dive Ball]" }, - { 0xD1BEA82EAAE529A7, "Watt Trader 1 [Nest Ball]" }, - { 0xD1BEA52EAAE5248E, "Watt Trader 1 [Repeat Ball]" }, - { 0xD1BEA62EAAE52641, "Watt Trader 1 [Timer Ball]" }, - { 0xD1BEA32EAAE52128, "Watt Trader 1 [Luxury Ball]" }, - { 0xD1BEA42EAAE522DB, "Watt Trader 1 [Dusk Ball]" }, - { 0xD1BEA12EAAE51DC2, "Watt Trader 1 [Heal Ball]" }, - { 0xD1BEA22EAAE51F75, "Watt Trader 1 [Quick Ball]" }, - - { 0xD1C20F2EAAE80E83, "Watt Trader 2 [Net Ball]" }, - { 0xD1C20E2EAAE80CD0, "Watt Trader 2 [Dive Ball]" }, - { 0xD1C2112EAAE811E9, "Watt Trader 2 [Nest Ball]" }, - { 0xD1C2102EAAE81036, "Watt Trader 2 [Repeat Ball]" }, - { 0xD1C2132EAAE8154F, "Watt Trader 2 [Timer Ball]" }, - { 0xD1C2122EAAE8139C, "Watt Trader 2 [Luxury Ball]" }, - { 0xD1C2152EAAE818B5, "Watt Trader 2 [Dusk Ball]" }, - { 0xD1C2142EAAE81702, "Watt Trader 2 [Heal Ball]" }, - { 0xD1C2172EAAE81C1B, "Watt Trader 2 [Quick Ball]" }, - - { 0xD1C2162EAAE81A68, "Watt Trader 3 [Net Ball]" }, - { 0xD1B79D2EAADEF848, "Watt Trader 3 [Dive Ball]" }, - { 0xD1B79E2EAADEF9FB, "Watt Trader 3 [Nest Ball]" }, - { 0xD1B79F2EAADEFBAE, "Watt Trader 3 [Repeat Ball]" }, - { 0xD1B7A02EAADEFD61, "Watt Trader 3 [Timer Ball]" }, - { 0xD1B7A12EAADEFF14, "Watt Trader 3 [Luxury Ball]" }, - { 0xD1B7A22EAADF00C7, "Watt Trader 3 [Dusk Ball]" }, - { 0xD1B7A32EAADF027A, "Watt Trader 3 [Heal Ball]" }, - { 0xD1B7A42EAADF042D, "Watt Trader 3 [Quick Ball]" }, - - { 0xD1B7952EAADEEAB0, "Watt Trader 4 [Net Ball]" }, - { 0xD1B7962EAADEEC63, "Watt Trader 4 [Dive Ball]" }, - { 0xD1BB232EAAE211D1, "Watt Trader 4 [Nest Ball]" }, - { 0xD1BB222EAAE2101E, "Watt Trader 4 [Repeat Ball]" }, - { 0xD1BB212EAAE20E6B, "Watt Trader 4 [Timer Ball]" }, - { 0xD1BB202EAAE20CB8, "Watt Trader 4 [Luxury Ball]" }, - { 0xD1BB272EAAE2189D, "Watt Trader 4 [Dusk Ball]" }, - { 0xD1BB262EAAE216EA, "Watt Trader 4 [Heal Ball]" }, - { 0xD1BB252EAAE21537, "Watt Trader 4 [Quick Ball]" }, - - { 0xD1BB242EAAE21384, "Watt Trader 5 [Net Ball]" }, - { 0xD1BB1B2EAAE20439, "Watt Trader 5 [Dive Ball]" }, - { 0xD1BB1A2EAAE20286, "Watt Trader 5 [Nest Ball]" }, - { 0xD1CC212EAAF0819E, "Watt Trader 5 [Repeat Ball]" }, - { 0xD1CC222EAAF08351, "Watt Trader 5 [Timer Ball]" }, - { 0xD1CC1F2EAAF07E38, "Watt Trader 5 [Luxury Ball]" }, - { 0xD1CC202EAAF07FEB, "Watt Trader 5 [Dusk Ball]" }, - { 0xD1CC252EAAF0886A, "Watt Trader 5 [Heal Ball]" }, - { 0xD1CC262EAAF08A1D, "Watt Trader 5 [Quick Ball]" }, - - { 0xD1CC232EAAF08504, "Watt Trader 6 [Net Ball]" }, - { 0xD1CC242EAAF086B7, "Watt Trader 6 [Dive Ball]" }, - { 0xD1CC192EAAF07406, "Watt Trader 6 [Repeat Ball]" }, - { 0xD1CC1A2EAAF075B9, "Watt Trader 6 [Quick Ball]" }, - { 0xD1CFA72EAAF39B27, "Watt Trader 6 [Heal Ball]" }, - - // Isle of Armor - { 0x5870C0165650F6A5, "Fields of Honor [Berry Shop]" }, - - // Crown Tundra - { 0x81DA6390A03C7E3F, "Freezington [Peddler]" }, - { 0x813C350B0B777943, "Snowslide Slope [Today's Highlight, TR00-TR09]" }, - { 0x813C360B0B777AF6, "Snowslide Slope [Today's Highlight, TR10-TR19]" }, - { 0x813C370B0B777CA9, "Snowslide Slope [Today's Highlight, TR20-TR29]" }, - { 0x813C380B0B777E5C, "Snowslide Slope [Today's Highlight, TR30-TR39]" }, - { 0x813C390B0B77800F, "Snowslide Slope [Today's Highlight, TR40-TR49]" }, - { 0x813C3A0B0B7781C2, "Snowslide Slope [Today's Highlight, TR50-TR59]" }, - { 0x813C3B0B0B778375, "Snowslide Slope [Today's Highlight, TR60-TR69]" }, - { 0x813C3C0B0B778528, "Snowslide Slope [Today's Highlight, TR70-TR79]" }, - { 0x813C3D0B0B7786DB, "Snowslide Slope [Today's Highlight, TR80-TR89]" }, - { 0x813F3A0B0B79B799, "Snowslide Slope [Today's Highlight, TR90-TR99]" }, - { 0xF49C86F8683842BF, "Max Lair [Dynite Ore Trader]" }, - }; - public void EditMoves() { var obj = ROM[GameFile.MoveStats]; // mini