mirror of
https://github.com/kwsch/PKHeX
synced 2024-12-24 19:33:10 +00:00
47071b41f3
Existing `get`/`set` logic is flawed in that it doesn't work on Big Endian operating systems, and it allocates heap objects when it doesn't need to. `System.Buffers.Binary.BinaryPrimitives` in the `System.Memory` NuGet package provides both Little Endian and Big Endian methods to read and write data; all the `get`/`set` operations have been reworked to use this new API. This removes the need for PKHeX's manual `BigEndian` class, as all functions are already covered by the BinaryPrimitives API. The `StringConverter` has now been rewritten to accept a Span to read from & write to, no longer requiring a temporary StringBuilder. Other Fixes included: - The Super Training UI for Gen6 has been reworked according to the latest block structure additions. - Cloning a Stadium2 Save File now works correctly (opening from the Folder browser list). - Checksum & Sanity properties removed from parent PKM class, and is now implemented via interface.
133 lines
5.8 KiB
C#
133 lines
5.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
using static PKHeX.Core.EncountersWC3;
|
|
|
|
namespace PKHeX.Core
|
|
{
|
|
public static class EncounterEvent
|
|
{
|
|
/// <summary>Event Database for Generation 3</summary>
|
|
public static IReadOnlyList<WC3> MGDB_G3 { get; private set; } = Array.Empty<WC3>();
|
|
|
|
/// <summary>Event Database for Generation 4</summary>
|
|
public static IReadOnlyList<PCD> MGDB_G4 { get; private set; } = Array.Empty<PCD>();
|
|
|
|
/// <summary>Event Database for Generation 5</summary>
|
|
public static IReadOnlyList<PGF> MGDB_G5 { get; private set; } = Array.Empty<PGF>();
|
|
|
|
/// <summary>Event Database for Generation 6</summary>
|
|
public static IReadOnlyList<WC6> MGDB_G6 { get; private set; } = Array.Empty<WC6>();
|
|
|
|
/// <summary>Event Database for Generation 7</summary>
|
|
public static IReadOnlyList<WC7> MGDB_G7 { get; private set; } = Array.Empty<WC7>();
|
|
|
|
/// <summary>Event Database for Generation 7 <see cref="GameVersion.GG"/></summary>
|
|
public static IReadOnlyList<WB7> MGDB_G7GG { get; private set; } = Array.Empty<WB7>();
|
|
|
|
/// <summary>Event Database for Generation 8</summary>
|
|
public static IReadOnlyList<WC8> MGDB_G8 { get; private set; } = Array.Empty<WC8>();
|
|
|
|
/// <summary>Event Database for Generation 8 <see cref="GameVersion.BDSP"/></summary>
|
|
public static IReadOnlyList<WB8> MGDB_G8B { get; private set; } = Array.Empty<WB8>();
|
|
|
|
/// <summary>Indicates if the databases are initialized.</summary>
|
|
public static bool Initialized => MGDB_G3.Count != 0;
|
|
|
|
private static PCD[] GetPCDDB(ReadOnlySpan<byte> bin) => Get(bin, PCD.Size, d => new PCD(d));
|
|
private static PGF[] GetPGFDB(ReadOnlySpan<byte> bin) => Get(bin, PGF.Size, d => new PGF(d));
|
|
|
|
private static WC6[] GetWC6DB(ReadOnlySpan<byte> wc6bin, ReadOnlySpan<byte> wc6full) => WC6Full.GetArray(wc6full, wc6bin);
|
|
private static WC7[] GetWC7DB(ReadOnlySpan<byte> wc7bin, ReadOnlySpan<byte> wc7full) => WC7Full.GetArray(wc7full, wc7bin);
|
|
|
|
private static WB7[] GetWB7DB(ReadOnlySpan<byte> bin) => Get(bin, WB7.SizeFull, d => new WB7(d));
|
|
private static WC8[] GetWC8DB(ReadOnlySpan<byte> bin) => Get(bin, WC8.Size, d => new WC8(d));
|
|
private static WB8[] GetWB8DB(ReadOnlySpan<byte> bin) => Get(bin, WB8.Size, d => new WB8(d));
|
|
|
|
private static T[] Get<T>(ReadOnlySpan<byte> bin, int size, Func<byte[], T> ctor)
|
|
{
|
|
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;
|
|
}
|
|
|
|
public static void RefreshMGDB(params string[] paths)
|
|
{
|
|
ICollection<PCD> g4 = GetPCDDB(Util.GetBinaryResource("wc4.pkl"));
|
|
ICollection<PGF> g5 = GetPGFDB(Util.GetBinaryResource("pgf.pkl"));
|
|
ICollection<WC6> g6 = GetWC6DB(Util.GetBinaryResource("wc6.pkl"), Util.GetBinaryResource("wc6full.pkl"));
|
|
ICollection<WC7> g7 = GetWC7DB(Util.GetBinaryResource("wc7.pkl"), Util.GetBinaryResource("wc7full.pkl"));
|
|
ICollection<WB7> b7 = GetWB7DB(Util.GetBinaryResource("wb7full.pkl"));
|
|
ICollection<WC8> g8 = GetWC8DB(Util.GetBinaryResource("wc8.pkl"));
|
|
ICollection<WB8> b8 = GetWB8DB(Util.GetBinaryResource("wb8.pkl"));
|
|
|
|
foreach (var gift in paths.Where(Directory.Exists).SelectMany(MysteryUtil.GetGiftsFromFolder))
|
|
{
|
|
static void AddOrExpand<T>(ref ICollection<T> arr, T obj)
|
|
{
|
|
if (arr is HashSet<T> h)
|
|
h.Add(obj);
|
|
else
|
|
arr = new HashSet<T>(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;
|
|
}
|
|
}
|
|
|
|
static T[] SetArray<T>(ICollection<T> 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<T>)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_G8B = SetArray(b8);
|
|
}
|
|
|
|
public static IEnumerable<MysteryGift> GetAllEvents(bool sorted = true)
|
|
{
|
|
var regular = new IReadOnlyList<MysteryGift>[]
|
|
{
|
|
MGDB_G4,
|
|
MGDB_G5,
|
|
MGDB_G6,
|
|
MGDB_G7,
|
|
MGDB_G7GG,
|
|
MGDB_G8,
|
|
MGDB_G8B,
|
|
}.SelectMany(z => z);
|
|
regular = regular.Where(mg => !mg.IsItem && mg.IsPokémon && mg.Species > 0);
|
|
var result = MGDB_G3.Concat(regular);
|
|
if (sorted)
|
|
result = result.OrderBy(mg => mg.Species);
|
|
return result;
|
|
}
|
|
}
|
|
}
|