using System; using System.Collections.Generic; using System.IO; using System.Linq; using static PKHeX.Core.EncountersWC3; namespace PKHeX.Core; /// /// Helper class that stores references to all the event data templates. /// public static class EncounterEvent { /// Event Database for Generation 3 public static IReadOnlyList MGDB_G3 { get; private set; } = Array.Empty(); /// Event Database for Generation 4 public static IReadOnlyList MGDB_G4 { get; private set; } = Array.Empty(); /// Event Database for Generation 5 public static IReadOnlyList MGDB_G5 { get; private set; } = Array.Empty(); /// Event Database for Generation 6 public static IReadOnlyList MGDB_G6 { get; private set; } = Array.Empty(); /// Event Database for Generation 7 public static IReadOnlyList MGDB_G7 { get; private set; } = Array.Empty(); /// Event Database for Generation 7 public static IReadOnlyList MGDB_G7GG { get; private set; } = Array.Empty(); /// Event Database for Generation 8 public static IReadOnlyList MGDB_G8 { get; private set; } = Array.Empty(); /// Event Database for Generation 8 public static IReadOnlyList MGDB_G8A { get; private set; } = Array.Empty(); /// Event Database for Generation 8 public static IReadOnlyList MGDB_G8B { get; private set; } = Array.Empty(); /// Event Database for Generation 9 public static IReadOnlyList MGDB_G9 { get; private set; } = Array.Empty(); /// Indicates if the databases are initialized. public static bool Initialized => MGDB_G3.Count != 0; private static PCD[] GetPCDDB(ReadOnlySpan bin) => Get(bin, PCD.Size, static d => new PCD(d)); private static PGF[] GetPGFDB(ReadOnlySpan bin) => Get(bin, PGF.Size, static d => new PGF(d)); private static WC6[] GetWC6DB(ReadOnlySpan wc6bin, ReadOnlySpan wc6full) => WC6Full.GetArray(wc6full, wc6bin); private static WC7[] GetWC7DB(ReadOnlySpan wc7bin, ReadOnlySpan wc7full) => WC7Full.GetArray(wc7full, wc7bin); private static WB7[] GetWB7DB(ReadOnlySpan bin) => Get(bin, WB7.SizeFull, static d => new WB7(d)); private static WC8[] GetWC8DB(ReadOnlySpan bin) => Get(bin, WC8.Size, static d => new WC8(d)); private static WB8[] GetWB8DB(ReadOnlySpan bin) => Get(bin, WB8.Size, static d => new WB8(d)); private static WA8[] GetWA8DB(ReadOnlySpan bin) => Get(bin, WA8.Size, static d => new WA8(d)); private static WC9[] GetWC9DB(ReadOnlySpan bin) => Get(bin, WC9.Size, static d => new WC9(d)); private static T[] Get(ReadOnlySpan bin, int size, Func ctor) { // bin is a multiple of size // bin.Length % size == 0 var result = new T[bin.Length / size]; System.Diagnostics.Debug.Assert(result.Length * size == bin.Length); for (int i = 0; i < result.Length; i++) { var offset = i * size; var slice = bin.Slice(offset, size).ToArray(); result[i] = ctor(slice); } return result; } /// /// Reloads the stored event templates. /// /// External folder(s) to source individual mystery gift template files from. public static void RefreshMGDB(params string[] paths) { ICollection g4 = GetPCDDB(Util.GetBinaryResource("wc4.pkl")); ICollection g5 = GetPGFDB(Util.GetBinaryResource("pgf.pkl")); ICollection g6 = GetWC6DB(Util.GetBinaryResource("wc6.pkl"), Util.GetBinaryResource("wc6full.pkl")); ICollection g7 = GetWC7DB(Util.GetBinaryResource("wc7.pkl"), Util.GetBinaryResource("wc7full.pkl")); ICollection b7 = GetWB7DB(Util.GetBinaryResource("wb7full.pkl")); ICollection g8 = GetWC8DB(Util.GetBinaryResource("wc8.pkl")); ICollection b8 = GetWB8DB(Util.GetBinaryResource("wb8.pkl")); ICollection a8 = GetWA8DB(Util.GetBinaryResource("wa8.pkl")); ICollection g9 = GetWC9DB(Util.GetBinaryResource("wc9.pkl")); // Load external files // For each file, load the gift object into the appropriate list. var gifts = GetGifts(paths); foreach (var gift in gifts) { static void AddOrExpand(ref ICollection arr, T obj) { if (arr is HashSet h) h.Add(obj); else arr = new HashSet(arr) {obj}; } switch (gift) { case PCD pcd: AddOrExpand(ref g4, pcd); continue; case PGF pgf: AddOrExpand(ref g5, pgf); continue; case WC6 wc6: AddOrExpand(ref g6, wc6); continue; case WC7 wc7: AddOrExpand(ref g7, wc7); continue; case WB7 wb7: AddOrExpand(ref b7, wb7); continue; case WC8 wc8: AddOrExpand(ref g8, wc8); continue; case WB8 wb8: AddOrExpand(ref b8, wb8); continue; case WA8 wa8: AddOrExpand(ref a8, wa8); continue; case WC9 wc9: AddOrExpand(ref g9, wc9); continue; } } static T[] SetArray(ICollection arr) { if (arr is T[] x) return x; // rather than use Linq to build an array, just do it the quick way directly. var result = new T[arr.Count]; ((HashSet)arr).CopyTo(result, 0); return result; } MGDB_G3 = Encounter_WC3; // hardcoded MGDB_G4 = SetArray(g4); MGDB_G5 = SetArray(g5); MGDB_G6 = SetArray(g6); MGDB_G7 = SetArray(g7); MGDB_G7GG = SetArray(b7); MGDB_G8 = SetArray(g8); MGDB_G8A = SetArray(a8); MGDB_G8B = SetArray(b8); MGDB_G9 = SetArray(g9); } private static IEnumerable GetGifts(IEnumerable paths) { foreach (var path in paths) { if (!Directory.Exists(path)) continue; var gifts = MysteryUtil.GetGiftsFromFolder(path); foreach (var gift in gifts) yield return gift; } } /// /// Gets all event gifts. /// /// If true, the result will be sorted by ascending species ID. Otherwise, will be ordered by generation ascending. public static IEnumerable GetAllEvents(bool sorted = true) { var regular = new IReadOnlyList[] { MGDB_G4, MGDB_G5, MGDB_G6, MGDB_G7, MGDB_G7GG, MGDB_G8, MGDB_G8A, MGDB_G8B, MGDB_G9, }.SelectMany(z => z); regular = regular.Where(mg => !mg.IsItem && mg.IsEntity && mg.Species > 0); var result = MGDB_G3.Concat(regular); if (sorted) result = result.OrderBy(mg => mg.Species); return result; } }