diff --git a/PKHeX.Core/Editing/Applicators/TechnicalRecordApplicator.cs b/PKHeX.Core/Editing/Applicators/TechnicalRecordApplicator.cs index cbb18af8f..af452d48d 100644 --- a/PKHeX.Core/Editing/Applicators/TechnicalRecordApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/TechnicalRecordApplicator.cs @@ -124,10 +124,12 @@ public static void SetRecordFlagsAll(this ITechRecord pk, ReadOnlySpan false, }; + /// public static void SetRecordFlags(this T pk, TechnicalRecordApplicatorOption option) where T : PKM, ITechRecord => SetRecordFlags(pk, pk, option); + /// public static void SetRecordFlags(this ITechRecord record, PKM pk, TechnicalRecordApplicatorOption option) { record.ClearRecordFlags(); @@ -142,6 +144,13 @@ public static void SetRecordFlags(this ITechRecord record, PKM pk, TechnicalReco SetRecordFlagsInternal(record, pk, option, la); } + /// + /// Applies the Technical Record flags based on the . + /// + /// Object to apply to. + /// Object to apply to, but base type for other logic. + /// Option to apply. + /// Legality analysis to use for the option. public static void SetRecordFlags(this ITechRecord record, PKM pk, TechnicalRecordApplicatorOption option, LegalityAnalysis la) { record.ClearRecordFlags(); @@ -172,10 +181,28 @@ private static void SetRecordFlagsInternal(ITechRecord record, PKM pk, Technical } } +/// +/// Options for applying Technical Record flags. +/// public enum TechnicalRecordApplicatorOption { + /// + /// Do not apply any flags. Clear all flags. + /// None, + + /// + /// Apply all flags, regardless of legality. + /// ForceAll, + + /// + /// Apply legal flags based on the current moves. + /// LegalCurrent, + + /// + /// Apply legal flags based on all moves able to learn in the game it resides in. + /// LegalAll, } diff --git a/PKHeX.Core/Editing/Database/TrainerDatabase.cs b/PKHeX.Core/Editing/Database/TrainerDatabase.cs index eb4c10f69..2758fb1cc 100644 --- a/PKHeX.Core/Editing/Database/TrainerDatabase.cs +++ b/PKHeX.Core/Editing/Database/TrainerDatabase.cs @@ -1,5 +1,7 @@ +using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; namespace PKHeX.Core; @@ -25,17 +27,12 @@ public sealed class TrainerDatabase return GetTrainerFromGroup(version, language); if (Database.TryGetValue(version, out var list)) - return GetRandomChoice(list); + return list[GetRandomIndex(list.Count)]; return null; } - private static T GetRandomChoice(IReadOnlyList list) - { - if (list.Count == 1) - return list[0]; - return list[Util.Rand.Next(list.Count)]; - } + private static int GetRandomIndex(int count) => count == 1 ? 0 : Util.Rand.Next(count); /// /// Fetches an appropriate trainer based on the requested group. @@ -57,7 +54,8 @@ private static T GetRandomChoice(IReadOnlyList list) return new KeyValuePair>(z.Key, filtered); }).Where(z => z.Value.Count != 0).ToList(); } - return GetRandomTrainer(possible); + var span = CollectionsMarshal.AsSpan(possible); + return GetRandomTrainer(span); } /// @@ -80,15 +78,17 @@ private static T GetRandomChoice(IReadOnlyList list) return new KeyValuePair>(z.Key, filtered); }).Where(z => z.Value.Count != 0).ToList(); } - return GetRandomTrainer(possible); + var span = CollectionsMarshal.AsSpan(possible); + return GetRandomTrainer(span); } - private static ITrainerInfo? GetRandomTrainer(IReadOnlyList>> possible) + private static ITrainerInfo? GetRandomTrainer(ReadOnlySpan>> possible) { - if (possible.Count == 0) + if (possible.Length == 0) return null; - var group = GetRandomChoice(possible); - return GetRandomChoice(group.Value); + var group = possible[GetRandomIndex(possible.Length)]; + var span = group.Value; + return span[GetRandomIndex(span.Count)]; } /// diff --git a/PKHeX.Core/Game/GameStrings/GameStrings.cs b/PKHeX.Core/Game/GameStrings/GameStrings.cs index 8c45f8a0a..f8198752d 100644 --- a/PKHeX.Core/Game/GameStrings/GameStrings.cs +++ b/PKHeX.Core/Game/GameStrings/GameStrings.cs @@ -723,6 +723,7 @@ private string[] GetItemStrings9() static void InsertZero(Span arr, string insert) { + // TM #'s are always ending with ##, so insert before the last 2 characters foreach (ref var str in arr) str = str.Insert(str.Length - 2, insert); } diff --git a/PKHeX.Core/Legality/Bulk/BulkAnalysis.cs b/PKHeX.Core/Legality/Bulk/BulkAnalysis.cs index ac4eb0565..8d8808139 100644 --- a/PKHeX.Core/Legality/Bulk/BulkAnalysis.cs +++ b/PKHeX.Core/Legality/Bulk/BulkAnalysis.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; namespace PKHeX.Core.Bulk; @@ -36,7 +37,7 @@ public BulkAnalysis(SaveFile sav, BulkAnalysisSettings settings) SlotInfoLoader.AddFromSaveFile(sav, list); list.RemoveAll(IsEmptyData); AllData = list; - AllAnalysis = GetIndividualAnalysis(list); + AllAnalysis = GetIndividualAnalysis(CollectionsMarshal.AsSpan(list)); CloneFlags = new bool[AllData.Count]; ScanAll(); @@ -95,12 +96,12 @@ public void AddLine(SlotCache first, string msg, CheckIdentifier i, Severity s = Parse.Add(chk); } - private static LegalityAnalysis[] GetIndividualAnalysis(IReadOnlyList pkms) + private static LegalityAnalysis[] GetIndividualAnalysis(ReadOnlySpan list) { - var results = new LegalityAnalysis[pkms.Count]; - for (int i = 0; i < pkms.Count; i++) - results[i] = Get(pkms[i]); - return results; + var result = new LegalityAnalysis[list.Length]; + for (int i = 0; i < list.Length; i++) + result[i] = Get(list[i]); + return result; } private static LegalityAnalysis Get(SlotCache cache) => new(cache.Entity, cache.SAV.Personal, cache.Source.Type); diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1GBEra.cs b/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1GBEra.cs index af35893bf..2b3c4a3db 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1GBEra.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1GBEra.cs @@ -8,13 +8,13 @@ internal static class Encounters1GBEra private static EncounterGift1[] GetGifts(ReadOnlySpan bin) { - const int Size = EncounterGift1.SerializedSize; - var result = new EncounterGift1[bin.Length / Size]; + const int size = EncounterGift1.SerializedSize; + var result = new EncounterGift1[bin.Length / size]; for (int i = 0; i < result.Length; i++) { - var data = bin[..Size]; + var data = bin[..size]; result[i] = new EncounterGift1(data); - bin = bin[Size..]; + bin = bin[size..]; } return result; } diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen2/Encounters2GBEra.cs b/PKHeX.Core/Legality/Encounters/Data/Gen2/Encounters2GBEra.cs index f0a483869..08e40cc1a 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen2/Encounters2GBEra.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen2/Encounters2GBEra.cs @@ -8,13 +8,13 @@ internal static class Encounters2GBEra private static EncounterGift2[] GetGifts(ReadOnlySpan bin) { - const int Size = EncounterGift2.SerializedSize; - var result = new EncounterGift2[bin.Length / Size]; + const int size = EncounterGift2.SerializedSize; + var result = new EncounterGift2[bin.Length / size]; for (int i = 0; i < result.Length; i++) { - var data = bin[..Size]; + var data = bin[..size]; result[i] = new EncounterGift2(data); - bin = bin[Size..]; + bin = bin[size..]; } return result; } diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs b/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs index c7799ad19..cfe18554a 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs @@ -10,7 +10,7 @@ namespace PKHeX.Core; /// Generation 3 Gifts /// /// -/// Generation 3 has a wide range of PIDIV types and other restrictions, and was never consistently stored in raw bytes. +/// Generation 3 has a wide range of PID/IV types and other restrictions, and was never consistently stored in raw bytes. /// Normally we'd just load the data from a binary, but without raw data... hard-code everything by hand. /// internal static class EncountersWC3 diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs index b5a577dbc..a148074c6 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs @@ -72,7 +72,7 @@ public static void FindVerifiedEncounter(PKM pk, LegalInfo info) { if (!info.FrameMatches) // if false, all valid RNG frame matches have already been consumed info.Parse.Add(new CheckResult(ParseSettings.Settings.FramePattern.GetSeverity(info.Generation), CheckIdentifier.PID, LEncConditionBadRNGFrame)); - else if (!info.PIDIVMatches) // if false, all valid PIDIV matches have already been consumed + else if (!info.PIDIVMatches) // if false, all valid PID/IV matches have already been consumed info.Parse.Add(new CheckResult(Severity.Invalid, CheckIdentifier.PID, LPIDTypeMismatch)); } } diff --git a/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot8GO.cs b/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot8GO.cs index 1946240cd..f7e07e95f 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot8GO.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot8GO.cs @@ -300,7 +300,7 @@ public bool IsWithinDistributionWindow(DateOnly date) return this.IsWithinStartEnd(stamp); } - private bool IsFormArgIncorrect(ISpeciesForm pk) => Species switch + private bool IsFormArgIncorrect(T pk) where T : ISpeciesForm => Species switch { // Evolved without Form Argument changing from default (int)Yamask when pk.Species != Species && Form == 1 => pk is IFormArgument { FormArgument: 0 }, diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs index e0ae46418..8bd3bc7ad 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs @@ -23,7 +23,7 @@ public sealed record EncounterTrade1 : IEncounterable, IEncounterMatch, IFixedTr public bool IsFixedTrainer => true; public bool IsFixedNickname => true; - private string[] Nicknames { get; } + private readonly ReadOnlyMemory Nicknames; public ushort Species { get; } public byte Form => 0; public bool EvolveOnTrade { get; init; } @@ -61,7 +61,7 @@ private bool IsNicknameValid(PKM pk, ReadOnlySpan nick) // Special consideration for Hiragana strings that are transferred if (Version == GameVersion.YW && Species == (int)Core.Species.Dugtrio) return nick is "ぐりお"; - return nick.SequenceEqual(Nicknames[1]); + return nick.SequenceEqual(Nicknames.Span[(int)LanguageID.Japanese]); } return GetNicknameIndex(nick) >= 2; @@ -83,7 +83,7 @@ private static bool IsTrainerNameValid(PKM pk) return trainer.SequenceEqual(expect); } - private int GetNicknameIndex(ReadOnlySpan nickname) => GetIndex(nickname, Nicknames); + private int GetNicknameIndex(ReadOnlySpan nickname) => GetIndex(nickname, Nicknames.Span); private static int GetIndex(ReadOnlySpan name, ReadOnlySpan arr) { @@ -125,7 +125,7 @@ public PK1 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) CatchRate = pi.CatchRate, DV16 = EncounterUtil.GetRandomDVs(Util.Rand), - Nickname = Nicknames[lang], + Nickname = Nicknames.Span[lang], TID16 = tr.TID16, Type1 = pi.Type1, Type2 = pi.Type2, @@ -145,7 +145,7 @@ public PK1 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) #region Matching public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => IsTrainerNameValid(pk); public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => IsNicknameValid(pk, nickname); - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; public EncounterMatchRating GetMatchRating(PKM pk) { diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterGift2.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterGift2.cs index 99819f4bb..e78844434 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterGift2.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterGift2.cs @@ -256,7 +256,7 @@ private static bool IsTrainerName(PKM pk, [ConstantExpected] string name) return ot[..len].SequenceEqual(name); } - private bool IsTrainerIDValid(ITrainerID16 pk) => Trainer switch + private bool IsTrainerIDValid(T pk) where T : ITrainerID16 => Trainer switch { Recipient => true, GiftStadiumJPN => pk.TID16 == TrainerIDStadiumJPN, diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterTrade2.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterTrade2.cs index fab7a4e5b..b6f786aad 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterTrade2.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterTrade2.cs @@ -29,8 +29,8 @@ public sealed record EncounterTrade2 : IEncounterable, IEncounterMatch, IFixedTr public byte LevelMin => Level; public byte LevelMax => 100; - private string[] TrainerNames { get; } - private string[] Nicknames { get; } + private readonly ReadOnlyMemory TrainerNames; + private readonly ReadOnlyMemory Nicknames; public byte Gender { get; init; } public byte OTGender { get; init; } @@ -66,8 +66,8 @@ public PK2 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) MetLocation = Location, - Nickname = Nicknames[lang], - OriginalTrainerName = TrainerNames[lang], + Nickname = Nicknames.Span[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerFriendship = pi.BaseFriendship, }; @@ -151,17 +151,17 @@ private int DetectLanguage(PKM pk, ReadOnlySpan trainer, ReadOnlySpan trainer, ReadOnlySpan trainer, ReadOnlySpan nickname) { + var names = Nicknames.Span; if (pk.Japanese) { - if (!nickname.SequenceEqual(Nicknames[(int)LanguageID.Japanese])) + if (!nickname.SequenceEqual(names[(int)LanguageID.Japanese])) return -1; return (int)LanguageID.Japanese; } if (pk.Korean) { - if (!nickname.SequenceEqual(Nicknames[(int)LanguageID.Korean])) + if (!nickname.SequenceEqual(names[(int)LanguageID.Korean])) return -1; return (int)LanguageID.Korean; } - for (int i = 2; i < Nicknames.Length; i++) + for (int i = 2; i < names.Length; i++) { if (i == (int)LanguageID.UNUSED_6) continue; - if (nickname.SequenceEqual(Nicknames[i])) + if (nickname.SequenceEqual(names[i])) return i; } return -1; @@ -205,20 +206,21 @@ private int DetectLanguageNickname(PKM pk, ReadOnlySpan nickname) private int DetectLanguageTrainer(PKM pk, ReadOnlySpan trainer) { + var names = TrainerNames.Span; if (pk.Japanese) { - if (!trainer.SequenceEqual(TrainerNames[(int)LanguageID.Japanese])) + if (!trainer.SequenceEqual(names[(int)LanguageID.Japanese])) return -1; return (int)LanguageID.Japanese; } if (pk.Korean) { - if (!trainer.SequenceEqual(TrainerNames[(int)LanguageID.Korean])) + if (!trainer.SequenceEqual(names[(int)LanguageID.Korean])) return -1; return (int)LanguageID.Korean; } - for (int i = 2; i < TrainerNames.Length; i++) + for (int i = 2; i < names.Length; i++) { if (i == (int)LanguageID.UNUSED_6) continue; @@ -230,7 +232,7 @@ private int DetectLanguageTrainer(PKM pk, ReadOnlySpan trainer) private bool IsTrainerMatchExact(PKM pk, ReadOnlySpan trainer, int language) { - var expect = pk.Format < 7 ? TrainerNames[language] : GetExpectedOT(Species, language, pk.Language); + var expect = pk.Format < 7 ? TrainerNames.Span[language] : GetExpectedOT(Species, language, pk.Language); return trainer.SequenceEqual(expect); } @@ -239,7 +241,7 @@ private bool IsTrainerMatchExact(PKM pk, ReadOnlySpan trainer, int languag // Can't transfer verbatim with Spanish origin glyphs to French VC. (int)Voltorb when language == (int)LanguageID.Spanish && pkLanguage == (int)LanguageID.French => "FALCçN", // FALCÁN (int)Shuckle when language == (int)LanguageID.Spanish && pkLanguage == (int)LanguageID.French => "MANôA", // MANÍA - _ => TrainerNames[language], + _ => TrainerNames.Span[language], }; // Already required for encounter matching. @@ -275,7 +277,7 @@ public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int _) return lang != -1; } - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; #endregion } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterGift3Colo.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterGift3Colo.cs index 99f33f597..dd1958c16 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterGift3Colo.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterGift3Colo.cs @@ -21,7 +21,7 @@ public sealed record EncounterGift3Colo : IEncounterable, IEncounterMatch, IEnco public bool IsFixedTrainer => true; public bool IsJapaneseBonusDisk => Version == GameVersion.R; - private readonly string[] TrainerNames; + private readonly ReadOnlyMemory TrainerNames; public ushort Species { get; } public byte Level { get; } public required byte Location { get; init; } @@ -29,7 +29,7 @@ public sealed record EncounterGift3Colo : IEncounterable, IEncounterMatch, IEnco public required ushort TID16 { get; init; } public required byte OriginalTrainerGender { get; init; } - public EncounterGift3Colo(ushort species, byte level, string[] trainers, GameVersion game) + public EncounterGift3Colo(ushort species, byte level, ReadOnlyMemory trainers, GameVersion game) { Species = species; Level = level; @@ -63,7 +63,7 @@ public CK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Ball = (byte)Ball.Poke, Language = lang, - OriginalTrainerName = TrainerNames[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerGender = OriginalTrainerGender, ID32 = TID16, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), @@ -166,7 +166,7 @@ public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) if ((uint)language >= TrainerNames.Length) return false; - var expect = TrainerNames[language].AsSpan(); + var expect = TrainerNames.Span[language].AsSpan(); if (pk is CK3 && expect.SequenceEqual(trainer)) return true; // not yet transferred to mainline Gen3 diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterStatic3.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterStatic3.cs index a86317782..1a1341b02 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterStatic3.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterStatic3.cs @@ -196,8 +196,8 @@ public bool IsCompatible(PIDType type, PKM pk) private static bool IsRoamerPIDIV(PIDType val, PKM pk) { - // Roamer PIDIV is always Method 1. - // M1 is checked before M1R. A M1R PIDIV can also be a M1 PIDIV, so check that collision. + // Roamer PID/IV is always Method 1. + // M1 is checked before M1R. A M1R PID/IV can also be a M1 PID/IV, so check that collision. if (PIDType.Method_1_Roamer == val) return true; if (PIDType.Method_1 != val) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterTrade3.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterTrade3.cs index 9728495f5..18e4636dc 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterTrade3.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterTrade3.cs @@ -20,8 +20,8 @@ public sealed record EncounterTrade3 : IEncounterable, IEncounterMatch, IFixedTr public bool IsFixedNickname => true; public Nature Nature => (Nature)(PID % 25); - private string[] TrainerNames { get; } - private string[] Nicknames { get; } + private readonly ReadOnlyMemory TrainerNames; + private readonly ReadOnlyMemory Nicknames; public required AbilityPermission Ability { get; init; } public required byte Gender { get; init; } @@ -108,8 +108,8 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) // Italian LG Jynx untranslated from English name if (Species == (int)Core.Species.Jynx && version == GameVersion.LG && lang == (int)LanguageID.Italian) lang = 2; - pk.Nickname = Nicknames[lang]; - pk.OriginalTrainerName = TrainerNames[lang]; + pk.Nickname = Nicknames.Span[lang]; + pk.OriginalTrainerName = TrainerNames.Span[lang]; EncounterUtil.SetEncounterMoves(pk, Version, Level); SetPINGA(pk, criteria); @@ -164,9 +164,11 @@ public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) { if (Species == (int)Core.Species.Jynx && pk.Version == GameVersion.LG && language == (int)LanguageID.Italian) language = 2; - if (language == 0 || (uint)language >= TrainerNames.Length) + + var names = TrainerNames.Span; + if (language == 0 || (uint)language >= names.Length) return false; - var name = TrainerNames[language]; + var name = names[language]; if (pk.Context == EntityContext.Gen3) return trainer.SequenceEqual(name); @@ -179,9 +181,11 @@ public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) { if (Species == (int)Core.Species.Jynx && pk.Version == GameVersion.LG && language == (int)LanguageID.Italian) language = 2; - if (language == 0 || (uint)language >= TrainerNames.Length) + + var names = Nicknames.Span; + if (language == 0 || (uint)language >= names.Length) return false; - var name = Nicknames[language]; + var name = names[language]; if (pk.Context == EntityContext.Gen3) return nickname.SequenceEqual(name); @@ -192,7 +196,7 @@ public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) return nickname.SequenceEqual(tmp); } - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; #endregion } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterTrade3XD.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterTrade3XD.cs index c6c787cee..abb036361 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterTrade3XD.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterTrade3XD.cs @@ -32,13 +32,13 @@ public sealed record EncounterTrade3XD : IEncounterable, IEncounterMatch, IEncou public required ushort TID16 { get; init; } // SID: Based on player ID - private readonly string[] TrainerNames; + private readonly ReadOnlyMemory TrainerNames; - private readonly string[] Nicknames; + private readonly ReadOnlyMemory Nicknames; - public EncounterTrade3XD(ushort species, byte level, string[] trainer) : this(species, level, trainer, []) { } + public EncounterTrade3XD(ushort species, byte level, ReadOnlyMemory trainer) : this(species, level, trainer, ReadOnlyMemory.Empty) { } - public EncounterTrade3XD(ushort species, byte level, string[] trainer, string[] nicknames) + public EncounterTrade3XD(ushort species, byte level, ReadOnlyMemory trainer, ReadOnlyMemory nicknames) { Species = species; Level = level; @@ -72,7 +72,7 @@ public XK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Ball = (byte)Ball.Poke, FatefulEncounter = FatefulEncounter, Language = lang, - OriginalTrainerName = TrainerNames[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerGender = 0, TID16 = TID16, SID16 = tr.SID16, @@ -179,7 +179,7 @@ public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) return false; if (language == 0 || (uint)language >= TrainerNames.Length) return false; - var name = TrainerNames[language]; + var name = TrainerNames.Span[language]; if (pk.Context == EntityContext.Gen3) return trainer.SequenceEqual(name); if (IsSpanishDuking(language)) // Gen4+ @@ -195,7 +195,7 @@ public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) return true; if (language == 0 || (uint)language >= Nicknames.Length) return false; - var name = Nicknames[language]; + var name = Nicknames.Span[language]; if (pk.Context == EntityContext.Gen3) return nickname.SequenceEqual(name); @@ -204,5 +204,5 @@ public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) return nickname.SequenceEqual(tmp); } - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4PID.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4PID.cs index 7a3fa0f0d..16f3fd0fd 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4PID.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4PID.cs @@ -21,8 +21,8 @@ public sealed record EncounterTrade4PID public byte LevelMax => IsMetUnset ? Level : (byte)100; public ushort Location => IsMetUnset ? Locations.LinkTrade4NPC : MetLocation; - private readonly string[] TrainerNames; - private readonly string[] Nicknames; + private readonly ReadOnlyMemory TrainerNames; + private readonly ReadOnlyMemory Nicknames; public ushort Species { get; } public byte Level { get; } @@ -96,12 +96,12 @@ public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Version = version, Language = GetReceivedLanguage(lang, version), OriginalTrainerGender = OTGender, - OriginalTrainerName = TrainerNames[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = true, - Nickname = Nicknames[lang], + Nickname = Nicknames.Span[lang], HandlingTrainerName = tr.OT, HandlingTrainerGender = tr.Gender, @@ -148,9 +148,9 @@ private int GetLanguageDPPt(int lang, GameVersion game) #region Matching - public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames[language]); - public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames[language]); - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames.Span[language]); + public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames.Span[language]); + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; public bool IsMatchExact(PKM pk, EvoCriteria evo) { @@ -235,7 +235,7 @@ public int DetectOriginalLanguage(PKM pk) var len = pk.LoadString(pk.OriginalTrainerTrash, trainer); trainer = trainer[..len]; - var expect = TrainerNames[1]; + var expect = TrainerNames.Span[(int)LanguageID.Japanese]; var match = trainer.SequenceEqual(expect); if (!match) return 2; // verify strings with English locale instead. @@ -255,7 +255,8 @@ private int DetectTradeLanguageG4MeisterMagikarp(PKM pk, int currentLanguageID) var len = pk.LoadString(pk.NicknameTrash, nickname); nickname = nickname[..len]; - return nickname.SequenceEqual(Nicknames[(int)LanguageID.French]) ? (int)LanguageID.French : (int)LanguageID.Spanish; // Spanish is same as English + var french = Nicknames.Span[(int)LanguageID.French]; + return nickname.SequenceEqual(french) ? (int)LanguageID.French : (int)LanguageID.Spanish; // Spanish is same as English } return lang; @@ -274,7 +275,8 @@ private int DetectTradeLanguageG4SurgePikachu(PKM pk, int currentLanguageID) var len = pk.LoadString(pk.NicknameTrash, nickname); nickname = nickname[..len]; - return nickname.SequenceEqual(Nicknames[(int)LanguageID.Italian]) ? (int)LanguageID.Italian : (int)LanguageID.Spanish; + var italian = Nicknames.Span[(int)LanguageID.Italian]; + return nickname.SequenceEqual(italian) ? (int)LanguageID.Italian : (int)LanguageID.Spanish; } return lang; @@ -282,7 +284,7 @@ private int DetectTradeLanguageG4SurgePikachu(PKM pk, int currentLanguageID) private int DetectTradeLanguage(ReadOnlySpan actual, int currentLanguageID) { - var names = TrainerNames; + var names = TrainerNames.Span; for (int lang = 1; lang < names.Length; lang++) { var expect = names[lang]; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs index 54c7541e5..956a0c049 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs @@ -31,8 +31,8 @@ public sealed record EncounterTrade5B2W2 : IEncounterable, IEncounterMatch, IFix public IndividualValueSet IVs { get; init; } public Nature Nature { get; init; } = Nature.Random; - private readonly string[] TrainerNames; - private readonly string[] Nicknames; + private readonly ReadOnlyMemory TrainerNames; + private readonly ReadOnlyMemory Nicknames; private const string _name = "In-game Trade"; public string Name => _name; @@ -54,7 +54,7 @@ public EncounterTrade5B2W2(string[] names, GameVersion version) Version = version; Gender = FixedGenderUtil.GenderRandom; Nature = Nature.Random; - Nicknames = []; + Nicknames = ReadOnlyMemory.Empty; TrainerNames = names; IsFixedNickname = false; } @@ -86,12 +86,12 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Version = version, Language = lang, OriginalTrainerGender = OTGender, - OriginalTrainerName = TrainerNames[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = IsFixedNickname, - Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), + Nickname = IsFixedNickname ? Nicknames.Span[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; EncounterUtil.SetEncounterMoves(pk, version, Level); @@ -116,9 +116,9 @@ private void SetPINGA(PK5 pk, EncounterCriteria criteria, PersonalInfo5B2W2 pi) #region Matching - public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames[language]); - public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames[language]); - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames.Span[language]); + public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames.Span[language]); + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; public bool IsMatchExact(PKM pk, EvoCriteria evo) { diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5BW.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5BW.cs index 76b67516c..2ca9e9497 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5BW.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5BW.cs @@ -19,8 +19,8 @@ public sealed record EncounterTrade5BW : IEncounterable, IEncounterMatch, IFixed public byte LevelMin => Level; public byte LevelMax => Level; - private string[] TrainerNames { get; } - private string[] Nicknames { get; } + private readonly ReadOnlyMemory TrainerNames; + private readonly ReadOnlyMemory Nicknames; public required ushort Species { get; init; } public required byte Level { get; init; } @@ -86,12 +86,12 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Version = version, Language = lang == 1 ? 0 : lang, // Trades for JPN games have language ID of 0, not 1. OriginalTrainerGender = OTGender, - OriginalTrainerName = TrainerNames[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = IsFixedNickname, - Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), + Nickname = IsFixedNickname ? Nicknames.Span[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; EncounterUtil.SetEncounterMoves(pk, version, Level); @@ -106,9 +106,9 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) #region Matching - public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames[language]); - public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames[language]); - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames.Span[language]); + public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames.Span[language]); + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; public bool IsMatchExact(PKM pk, EvoCriteria evo) { diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs index c797f0ae8..9039bc14d 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs @@ -18,8 +18,8 @@ public sealed record EncounterTrade6 : IEncounterable, IEncounterMatch, IFixedTr public bool IsFixedTrainer => true; public bool IsFixedNickname { get; init; } = true; - private string[] TrainerNames { get; } - private string[] Nicknames { get; } + private readonly ReadOnlyMemory TrainerNames; + private readonly ReadOnlyMemory Nicknames; public required Nature Nature { get; init; } public required ushort ID32 { get; init; } @@ -84,7 +84,7 @@ public PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Version = version, Language = lang, OriginalTrainerGender = OTGender, - OriginalTrainerName = TrainerNames[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerMemory = OriginalTrainerMemory, OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity, @@ -93,7 +93,7 @@ public PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = IsFixedNickname, - Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), + Nickname = IsFixedNickname ? Nicknames.Span[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), HandlingTrainerName = tr.OT, HandlingTrainerGender = tr.Gender, @@ -119,14 +119,14 @@ public PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) #region Matching - public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames[language]); + public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames.Span[language]); public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) { if (Species is (ushort)Core.Species.Farfetchd && nickname is "Quacklin’" or "Quacklin'") return true; - return (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames[language]); + return (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames.Span[language]); } - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; public bool IsMatchExact(PKM pk, EvoCriteria evo) { diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs index 67a5ffda1..9a84c19af 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs @@ -22,8 +22,8 @@ public sealed record EncounterTrade7 : IEncounterable, IEncounterMatch, IFixedTr public bool IsFixedTrainer => true; public bool IsFixedNickname => true; - private string[] TrainerNames { get; } - private string[] Nicknames { get; } + private readonly ReadOnlyMemory TrainerNames; + private readonly ReadOnlyMemory Nicknames; public required Nature Nature { get; init; } public required uint ID32 { get; init; } @@ -83,7 +83,7 @@ public PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Version = version, Language = lang, OriginalTrainerGender = OTGender, - OriginalTrainerName = TrainerNames[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerMemory = OriginalTrainerMemory, OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity, @@ -92,7 +92,7 @@ public PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = true, - Nickname = Nicknames[lang], + Nickname = Nicknames.Span[lang], HandlingTrainerName = tr.OT, HandlingTrainerGender = tr.Gender, @@ -121,9 +121,9 @@ public PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) #region Matching - public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames[language]); - public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames[language]); - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames.Span[language]); + public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames.Span[language]); + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; public bool IsMatchExact(PKM pk, EvoCriteria evo) { diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterTrade7b.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterTrade7b.cs index 2d5284879..001ee0694 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterTrade7b.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterTrade7b.cs @@ -18,7 +18,7 @@ public sealed record EncounterTrade7b(GameVersion Version) : IEncounterable, IEn public bool IsFixedTrainer => true; public AbilityPermission Ability => AbilityPermission.Any12; - public required string[] TrainerNames { get; init; } + public required ReadOnlyMemory TrainerNames { get; init; } public required uint ID32 { get; init; } public required byte OTGender { get; init; } @@ -60,7 +60,7 @@ public PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Version = version, Language = lang, OriginalTrainerGender = OTGender, - OriginalTrainerName = TrainerNames[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerFriendship = pi.BaseFriendship, @@ -100,7 +100,7 @@ private void SetPINGA(PB7 pk, EncounterCriteria criteria, PersonalInfo7GG pi) #region Matching - public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames[language]); + public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames.Span[language]); public bool IsMatchExact(PKM pk, EvoCriteria evo) { diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs index e6e3e41be..d56c5c56e 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs @@ -70,6 +70,6 @@ protected override void SetTrainerName(ReadOnlySpan name, PK8 pk) (int)LanguageID.Korean => "연구원", (int)LanguageID.ChineseS => "研究员", (int)LanguageID.ChineseT => "研究員", - _ => ReadOnlySpan.Empty, + _ => [], }; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs index c2c83dbdf..4cd96e0ce 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs @@ -28,8 +28,8 @@ public sealed record EncounterTrade8 : IEncounterable, IEncounterMatch, IFixedTr public bool IsFixedTrainer => true; public bool IsFixedNickname { get; } - private string[] TrainerNames { get; } - private string[] Nicknames { get; } + private readonly ReadOnlyMemory TrainerNames; + private readonly ReadOnlyMemory Nicknames; public Nature Nature { get; init; } // always set by either constructor or initializer public required uint ID32 { get; init; } @@ -68,10 +68,10 @@ public EncounterTrade8(ReadOnlySpan names, byte index, GameVersion gam } [SetsRequiredMembers] - public EncounterTrade8(string[] trainerNames, GameVersion game, ushort species, byte level, byte memory, ushort arg, byte feel, byte intensity) + public EncounterTrade8(ReadOnlyMemory trainerNames, GameVersion game, ushort species, byte level, byte memory, ushort arg, byte feel, byte intensity) { Version = game; - Nicknames = []; + Nicknames = ReadOnlyMemory.Empty; TrainerNames = trainerNames; Species = species; Level = level; @@ -116,7 +116,7 @@ public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Version = version, Language = lang, OriginalTrainerGender = OTGender, - OriginalTrainerName = TrainerNames[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerMemory = OriginalTrainerMemory, OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity, @@ -125,7 +125,7 @@ public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = IsFixedNickname, - Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), + Nickname = IsFixedNickname ? Nicknames.Span[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), DynamaxLevel = DynamaxLevel, HandlingTrainerName = tr.OT, HandlingTrainerGender = tr.Gender, @@ -163,9 +163,9 @@ private void SetPINGA(PK8 pk, EncounterCriteria criteria, PersonalInfo8SWSH pi) #region Matching - public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames[language]); - public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames[language]); - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames.Span[language]); + public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames.Span[language]); + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; public bool IsMatchExact(PKM pk, EvoCriteria evo) { diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterTrade8b.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterTrade8b.cs index d74cdd938..4c34e42df 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterTrade8b.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterTrade8b.cs @@ -19,8 +19,8 @@ public sealed record EncounterTrade8b : IEncounterable, IEncounterMatch, IFixedT public bool IsFixedNickname => true; public GameVersion Version { get; } - private string[] TrainerNames { get; } - private string[] Nicknames { get; } + private readonly ReadOnlyMemory TrainerNames; + private readonly ReadOnlyMemory Nicknames; public required Nature Nature { get; init; } public required ushort ID32 { get; init; } @@ -91,12 +91,12 @@ public PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Version = version, Language = lang, OriginalTrainerGender = OTGender, - OriginalTrainerName = TrainerNames[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerFriendship = OriginalTrainerFriendship, IsNicknamed = IsFixedNickname, - Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), + Nickname = IsFixedNickname ? Nicknames.Span[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), HeightScalar = HeightScalar, WeightScalar = WeightScalar, HandlingTrainerName = tr.OT, @@ -121,9 +121,9 @@ public PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) #region Matching - public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames[language]); - public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames[language]); - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames.Span[language]); + public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames.Span[language]); + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; public EncounterMatchRating GetMatchRating(PKM pk) => EncounterMatchRating.Match; @@ -202,11 +202,13 @@ public int DetectMeisterMagikarpLanguage(ReadOnlySpan nick, ReadOnlySpan Nicknames.Length != 0; public GameVersion Version { get; } - private string[] TrainerNames { get; } - private string[] Nicknames { get; } + private readonly ReadOnlyMemory TrainerNames; + private readonly ReadOnlyMemory Nicknames; public required Nature Nature { get; init; } public required uint ID32 { get; init; } @@ -89,12 +89,12 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Version = version, Language = lang, OriginalTrainerGender = OTGender, - OriginalTrainerName = TrainerNames[lang], + OriginalTrainerName = TrainerNames.Span[lang], OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = IsFixedNickname, - Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), + Nickname = IsFixedNickname ? Nicknames.Span[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), HeightScalar = PokeSizeUtil.GetRandomScalar(rnd), WeightScalar = Weight.GetSizeValue(Weight != SizeType9.RANDOM ? FixedValueScale : default, ref xoro), @@ -147,9 +147,9 @@ private MoveType GetOriginalTeraType() #region Matching - public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames[language]); - public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames[language]); - public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : Nicknames[0]; + public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) => (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames.Span[language]); + public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) => (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames.Span[language]); + public string GetNickname(int language) => Nicknames.Span[(uint)language < Nicknames.Length ? language : 0]; private bool IsMatchNatureGenderShiny(PKM pk) { diff --git a/PKHeX.Core/Legality/Formatting/LegalityFormatting.cs b/PKHeX.Core/Legality/Formatting/LegalityFormatting.cs index 3bc7676f4..e743e3744 100644 --- a/PKHeX.Core/Legality/Formatting/LegalityFormatting.cs +++ b/PKHeX.Core/Legality/Formatting/LegalityFormatting.cs @@ -88,7 +88,7 @@ public static void AddEncounterInfo(LegalityAnalysis la, List lines) if (enc.Generation <= 2) lines.Add(string.Format(L_F0_1, nameof(GameVersion), enc.Version)); - // PIDIV + // PID/IV AddEncounterInfoPIDIV(la, lines); } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs index 01681c684..d0c93d8ef 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs @@ -77,7 +77,10 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo4 pi, EvoCriteria evo, usho return default; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species is (int)Species.Rotom && move switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species is (int)Species.Rotom && move switch { (int)Move.Overheat => option.IsPast() || current.Form == 1, (int)Move.HydroPump => option.IsPast() || current.Form == 2, diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs index 522ef90d9..60c633616 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs @@ -75,7 +75,10 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo4 pi, EvoCriteria evo, usho return default; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species is (int)Species.Rotom && move switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species is (int)Species.Rotom && move switch { (int)Move.Overheat => option.IsPast() || current.Form == 1, (int)Move.HydroPump => option.IsPast() || current.Form == 2, diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5B2W2.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5B2W2.cs index e981e4efb..4812dcff8 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5B2W2.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5B2W2.cs @@ -69,7 +69,10 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo5B2W2 pi, EvoCriteria evo, return default; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species switch { (int)Species.Keldeo => move is (int)Move.SecretSword, (int)Species.Meloetta => move is (int)Move.RelicSong, @@ -101,7 +104,7 @@ private static bool GetIsTM(PersonalInfo5B2W2 info, ushort move) return info.GetIsLearnTM(index); } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) + public void GetAllMoves(Span result, PKM _, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5BW.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5BW.cs index e57b85d95..e20b125dd 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5BW.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5BW.cs @@ -66,7 +66,10 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo5BW pi, EvoCriteria evo, us return default; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species switch { (int)Species.Keldeo => move is (int)Move.SecretSword, (int)Species.Meloetta => move is (int)Move.RelicSong, @@ -98,7 +101,7 @@ private static bool GetIsTM(PersonalInfo5BW info, ushort move) return info.GetIsLearnTM(index) && index != 94; // TM95 not available in this game } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) + public void GetAllMoves(Span result, PKM _, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6AO.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6AO.cs index f040f6606..542263858 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6AO.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6AO.cs @@ -70,7 +70,10 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo6AO pi, EvoCriteria evo, us return default; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species switch { (int)Species.Keldeo => move is (int)Move.SecretSword, (int)Species.Meloetta => move is (int)Move.RelicSong, @@ -92,7 +95,7 @@ private static bool GetIsTM(PersonalInfo6AO info, ushort move) return info.GetIsLearnTM(index); } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) + public void GetAllMoves(Span result, PKM _, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6XY.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6XY.cs index 5b6f31ae7..019caddbf 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6XY.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6XY.cs @@ -67,7 +67,10 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo6XY pi, EvoCriteria evo, us return default; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species switch { (int)Species.Keldeo => move is (int)Move.SecretSword, (int)Species.Meloetta => move is (int)Move.RelicSong, @@ -83,7 +86,7 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo6XY pi, EvoCriteria evo, us _ => false, }; - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) + public void GetAllMoves(Span result, PKM _, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7GG.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7GG.cs index 60f0542a6..53fc344fd 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7GG.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7GG.cs @@ -58,7 +58,7 @@ private static bool GetIsEnhancedTutor(ushort species, byte form, ushort move) return false; } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) + public void GetAllMoves(Span result, PKM _, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7SM.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7SM.cs index d942dfdc2..a3cc0a7c2 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7SM.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7SM.cs @@ -69,7 +69,10 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo7 pi, EvoCriteria evo, usho return default; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species switch { (int)Species.Pikachu or (int)Species.Raichu => move is (int)Move.VoltTackle, (int)Species.Necrozma => move switch @@ -93,7 +96,7 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo7 pi, EvoCriteria evo, usho _ => false, }; - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) + public void GetAllMoves(Span result, PKM _, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; @@ -132,9 +135,9 @@ public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceTy result[(int)Move.SecretSword] = true; else if (species is (int)Species.Meloetta) result[(int)Move.RelicSong] = true; - else if (species is (int)Species.Necrozma && pk.Form is 1) // Sun + else if (species is (int)Species.Necrozma && evo.Form is 1) // Sun result[(int)Move.SunsteelStrike] = true; - else if (species is (int)Species.Necrozma && pk.Form is 2) // Moon + else if (species is (int)Species.Necrozma && evo.Form is 2) // Moon result[(int)Move.MoongeistBeam] = true; } } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7USUM.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7USUM.cs index 9af6537a4..aba5cefad 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7USUM.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7USUM.cs @@ -72,7 +72,10 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo7 pi, EvoCriteria evo, usho return default; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species switch { (int)Species.Pikachu or (int)Species.Raichu => move is (int)Move.VoltTackle, (int)Species.Necrozma => move switch @@ -96,7 +99,7 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo7 pi, EvoCriteria evo, usho _ => false, }; - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) + public void GetAllMoves(Span result, PKM _, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; @@ -139,9 +142,9 @@ public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceTy result[(int)Move.SecretSword] = true; else if (species is (int)Species.Meloetta) result[(int)Move.RelicSong] = true; - else if (species is (int)Species.Necrozma && pk.Form is 1) // Sun + else if (species is (int)Species.Necrozma && evo.Form is 1) // Sun result[(int)Move.SunsteelStrike] = true; - else if (species is (int)Species.Necrozma && pk.Form is 2) // Moon + else if (species is (int)Species.Necrozma && evo.Form is 2) // Moon result[(int)Move.MoongeistBeam] = true; } } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8BDSP.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8BDSP.cs index efbaa81f2..c5b6db643 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8BDSP.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8BDSP.cs @@ -72,7 +72,10 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo8BDSP pi, EvoCriteria evo, return default; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species is (int)Species.Rotom && move switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species is (int)Species.Rotom && move switch { (int)Move.Overheat => option.IsPast() || current.Form == 1, (int)Move.HydroPump => option.IsPast() || current.Form == 2, @@ -89,7 +92,7 @@ private bool GetIsSharedEggMove(PersonalInfo8BDSP pi, ushort move) return GetEggMoves(baseSpecies, baseForm).Contains(move); } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) + public void GetAllMoves(Span result, PKM _, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8PLA.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8PLA.cs index 7f626ca9b..0d473db49 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8PLA.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8PLA.cs @@ -56,7 +56,10 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo8LA pi, EvoCriteria evo, us return default; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species is (int)Species.Rotom && move switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species is (int)Species.Rotom && move switch { (int)Move.Overheat => option.IsPast() || current.Form == 1, (int)Move.HydroPump => option.IsPast() || current.Form == 2, @@ -66,7 +69,7 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo8LA pi, EvoCriteria evo, us _ => false, }; - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) + public void GetAllMoves(Span result, PKM _, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8SWSH.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8SWSH.cs index dc20b852d..086731f61 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8SWSH.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8SWSH.cs @@ -74,7 +74,10 @@ public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo8SWSH pi, EvoCriteria evo, return default; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species switch { (int)Species.Necrozma => move switch { @@ -128,7 +131,7 @@ private static bool GetIsTR(PersonalInfo8SWSH info, PKM pk, EvoCriteria evo, ush return false; } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) + public void GetAllMoves(Span result, PKM _, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; @@ -167,11 +170,11 @@ public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceTy if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; - if (species is (int)Species.Rotom && pk.Form is not 0) + if (species is (int)Species.Rotom && evo.Form is not 0) result[MoveTutor.GetRotomFormMove(evo.Form)] = true; - else if (species is (int)Species.Necrozma && pk.Form is 1) // Sun + else if (species is (int)Species.Necrozma && evo.Form is 1) // Sun result[(int)Move.SunsteelStrike] = true; - else if (species is (int)Species.Necrozma && pk.Form is 2) // Moon + else if (species is (int)Species.Necrozma && evo.Form is 2) // Moon result[(int)Move.MoongeistBeam] = true; } } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource9SV.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource9SV.cs index 45d461f60..1303656ab 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource9SV.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource9SV.cs @@ -122,7 +122,10 @@ private static bool GetIsTM(PersonalInfo9SV info, PKM pk, ushort move, LearnOpti return false; } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species switch + private static bool GetIsEnhancedTutor(T1 evo, T2 current, ushort move, LearnOption option) + where T1 : ISpeciesForm + where T2 : ISpeciesForm + => evo.Species switch { (int)Species.Necrozma => move switch { @@ -149,7 +152,7 @@ private bool GetIsSharedEggMove(PersonalInfo9SV pi, ushort move) return GetEggMoves(baseSpecies, baseForm).Contains(move); } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) + public void GetAllMoves(Span result, PKM _, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; @@ -184,11 +187,11 @@ public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceTy if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; - if (species is (int)Species.Rotom && pk.Form is not 0) + if (species is (int)Species.Rotom && evo.Form is not 0) result[MoveTutor.GetRotomFormMove(evo.Form)] = true; - else if (species is (int)Species.Necrozma && pk.Form is 1) // Sun + else if (species is (int)Species.Necrozma && evo.Form is 1) // Sun result[(int)Move.SunsteelStrike] = true; - else if (species is (int)Species.Necrozma && pk.Form is 2) // Moon + else if (species is (int)Species.Necrozma && evo.Form is 2) // Moon result[(int)Move.MoongeistBeam] = true; } } diff --git a/PKHeX.Core/Legality/RNG/MethodFinder.cs b/PKHeX.Core/Legality/RNG/MethodFinder.cs index abec8248d..cf6cbcd6c 100644 --- a/PKHeX.Core/Legality/RNG/MethodFinder.cs +++ b/PKHeX.Core/Legality/RNG/MethodFinder.cs @@ -6,12 +6,12 @@ namespace PKHeX.Core; /// -/// Class containing logic to obtain a PKM's PIDIV method. +/// Class containing logic to obtain a PKM's PID/IV method. /// public static class MethodFinder { /// - /// Analyzes a to find a matching PIDIV method. + /// Analyzes a to find a matching PID/IV method. /// /// Input . /// object containing seed and method info. diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen8b/Roaming8bRNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen8b/Roaming8bRNG.cs index ae6ef0064..d8866315c 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen8b/Roaming8bRNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen8b/Roaming8bRNG.cs @@ -239,7 +239,7 @@ private static bool GetIsHeightWeightMatch(PKM pk, Xoroshiro128Plus8b xoro) return s.HeightScalar == height && s.WeightScalar == weight; } - private static uint GetRevisedPID(uint fakeTID, uint pid, ITrainerID32 tr) + private static uint GetRevisedPID(uint fakeTID, uint pid, T tr) where T : ITrainerID32 { var xor = GetShinyXor(pid, fakeTID); var newXor = GetShinyXor(pid, tr.ID32); diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen8b/Wild8bRNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen8b/Wild8bRNG.cs index 37986e1c2..511d3030d 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen8b/Wild8bRNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen8b/Wild8bRNG.cs @@ -142,7 +142,7 @@ public static bool TryApplyFromSeed(PKM pk, EncounterCriteria criteria, Shiny sh return true; } - private static uint GetRevisedPID(uint fakeTID, uint pid, ITrainerID32 tr) + private static uint GetRevisedPID(uint fakeTID, uint pid, T tr) where T : ITrainerID32 { var xor = GetShinyXor(pid, fakeTID); var newXor = GetShinyXor(pid, tr.ID32); diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen9/Tera9RNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen9/Tera9RNG.cs index 8236831f0..01f0c492b 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen9/Tera9RNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen9/Tera9RNG.cs @@ -70,22 +70,19 @@ public static byte GetTeraType(in ulong seed, GemType gem, in ushort species, in return type; var rand = new Xoroshiro128Plus(seed); - if (gem == GemType.Default) - { - var pivot = rand.NextInt(2); - return GetTeraTypeFromPersonal(species, form, pivot); - } if (gem == GemType.Random) - { return (byte)rand.NextInt(TeraTypeCount); - } - throw new ArgumentOutOfRangeException(nameof(gem), gem, null); + if (gem != GemType.Default) + throw new ArgumentOutOfRangeException(nameof(gem), gem, null); + var pivot = rand.NextInt(2); + return GetTeraTypeFromPersonal(species, form, pivot); } /// /// Checks if the original Tera Type matches either of the Personal Info types. /// - private static bool IsMatchType(IPersonalType pi, in byte original) => original == pi.Type1 || original == pi.Type2; + private static bool IsMatchType(T pi, in byte original) where T : IPersonalType + => original == pi.Type1 || original == pi.Type2; /// /// Checks if the original Tera Type matches the Personal Info type for the specified form. @@ -102,7 +99,7 @@ public static byte GetTeraType(in ulong seed, GemType gem, in ushort species, in ? IsMatchTeraTypePersonalAnyForm(species, original) : IsMatchTeraTypePersonal(species, form, original); - /// + /// public static bool IsMatchTeraTypePersonal(in ushort species, in byte form, in byte original) => IsMatchType(PersonalTable.SV[species, form], original); /// diff --git a/PKHeX.Core/Legality/RNG/PIDIV.cs b/PKHeX.Core/Legality/RNG/PIDIV.cs index 748a0365b..af748e2a4 100644 --- a/PKHeX.Core/Legality/RNG/PIDIV.cs +++ b/PKHeX.Core/Legality/RNG/PIDIV.cs @@ -21,7 +21,7 @@ namespace PKHeX.Core; /// The RNG seed which immediately generates the PID/IV (starting with PID or IVs, whichever comes first) [field: FieldOffset(0)] public ulong Seed64 { get; } - /// Type of PIDIV correlation + /// Type of PID/IV correlation [field: FieldOffset(8)] public PIDType Type { get; } [field: FieldOffset(9)] public LeadRequired Lead { get; init; } [field: FieldOffset(9)] public PIDType Mutated { get; init; } diff --git a/PKHeX.Core/MysteryGifts/WA8.cs b/PKHeX.Core/MysteryGifts/WA8.cs index 2a5bfa517..dabea5c72 100644 --- a/PKHeX.Core/MysteryGifts/WA8.cs +++ b/PKHeX.Core/MysteryGifts/WA8.cs @@ -560,7 +560,7 @@ private void SetPINGA(PA8 pk, EncounterCriteria criteria) _ => AbilityPermission.Any12H, }; - private uint GetPID(ITrainerID32 tr, ShinyType8 type) => type switch + private uint GetPID(T tr, ShinyType8 type) where T : ITrainerID32 => type switch { ShinyType8.Never => GetAntishiny(tr), // Random, Never Shiny ShinyType8.Random => Util.Rand32(), // Random, Any diff --git a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockCompare.cs b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockCompare.cs index 72103db51..0c9ded5e5 100644 --- a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockCompare.cs +++ b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockCompare.cs @@ -31,7 +31,7 @@ public SCBlockCompare(SCBlockAccessor s1, SCBlockAccessor s2, IEnumerable hs1, IEnumerable hs2) + private void LoadAddRemove(SCBlockAccessor s1, SCBlockAccessor s2, HashSet hs1, HashSet hs2) { var unique = new HashSet(hs1); unique.SymmetricExceptWith(hs2); @@ -51,7 +51,7 @@ private void LoadAddRemove(SCBlockAccessor s1, SCBlockAccessor s2, ICollection shared) + private void LoadChanged(SCBlockAccessor s1, SCBlockAccessor s2, IReadOnlySet shared) { foreach (var k in shared) { diff --git a/PKHeX.Core/Saves/Substructures/Gen4/Geonet4.cs b/PKHeX.Core/Saves/Substructures/Gen4/Geonet4.cs index 1d411d19f..4245fb927 100644 --- a/PKHeX.Core/Saves/Substructures/Gen4/Geonet4.cs +++ b/PKHeX.Core/Saves/Substructures/Gen4/Geonet4.cs @@ -67,7 +67,7 @@ public GeonetPoint GetCountrySubregion(byte country, byte subregion) { int index = ((country - 1) * 16) + (subregion / 4); int shift = 2 * (subregion % 4); - return (GeonetPoint)(((Data[index] & 0b11 << shift) >> shift)); + return (GeonetPoint)((Data[index] & 0b11 << shift) >> shift); } public void SetCountrySubregion(byte country, byte subregion, GeonetPoint point) diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs index 39b5a8d40..b88ce256a 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs @@ -113,10 +113,11 @@ private bool[] GetFlags() result[i] = GetFlag(i); return result; } - private void SetFlags(IReadOnlyList value) + + private void SetFlags(ReadOnlySpan value) { - ArgumentOutOfRangeException.ThrowIfNotEqual(value.Count, FlagSize); - for (int i = 0; i < value.Count; i++) + ArgumentOutOfRangeException.ThrowIfNotEqual(value.Length, FlagSize); + for (int i = 0; i < value.Length; i++) SetFlag(i, value[i]); } #endregion diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/PoffinSaveData8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/PoffinSaveData8b.cs index aefb9f154..b2c99d1ce 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/PoffinSaveData8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/PoffinSaveData8b.cs @@ -24,7 +24,7 @@ private static int GetPoffinOffset(int index) { if ((uint)index >= COUNT_POFFIN) throw new ArgumentOutOfRangeException(nameof(index)); - return (index * Poffin8b.SIZE); + return index * Poffin8b.SIZE; } private Memory GetPoffinSpan(int index) => Raw.Slice(GetPoffinOffset(index), Poffin8b.SIZE); diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs index c4046bf53..a585071ba 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs @@ -500,9 +500,9 @@ public override void SetDex(PKM pk) public override void SeenNone() { - Array.Clear(Galar.Data, 0, Galar.Data.Length); - Array.Clear(Rigel1.Data, 0, Rigel1.Data.Length); - Array.Clear(Rigel2.Data, 0, Rigel2.Data.Length); + Galar .Data.AsSpan().Clear(); + Rigel1.Data.AsSpan().Clear(); + Rigel2.Data.AsSpan().Clear(); } public override void CaughtNone() diff --git a/PKHeX.Core/Util/ComboItemUtil.cs b/PKHeX.Core/Util/ComboItemUtil.cs index 7147d206d..fe94bbb2b 100644 --- a/PKHeX.Core/Util/ComboItemUtil.cs +++ b/PKHeX.Core/Util/ComboItemUtil.cs @@ -9,7 +9,7 @@ public static partial class Util { public static List GetCountryRegionList(string textFile, string lang) { - string[] inputCSV = GetStringList(textFile); + var inputCSV = GetStringList(textFile); int index = GeoLocation.GetLanguageIndex(lang); var list = GetCBListFromCSV(inputCSV, index); if (list.Count > 1) diff --git a/PKHeX.Core/Util/RandUtil.cs b/PKHeX.Core/Util/RandUtil.cs index f2fc4790b..6c7ffe471 100644 --- a/PKHeX.Core/Util/RandUtil.cs +++ b/PKHeX.Core/Util/RandUtil.cs @@ -8,6 +8,6 @@ public static partial class Util public static Random Rand => Random.Shared; public static uint Rand32() => Rand32(Rand); - public static uint Rand32(this Random rnd) => ((uint)rnd.Next(1 << 30) << 2) | (uint)rnd.Next(1 << 2); + public static uint Rand32(this Random rnd) => (uint)rnd.NextInt64(); public static ulong Rand64(this Random rnd) => rnd.Rand32() | ((ulong)rnd.Rand32() << 32); } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs index e0dca91b5..0a6b84bae 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs @@ -685,21 +685,21 @@ private void ReadSubway() CHK_SWNPCMet.Checked = sw.NPCMet; // Current Run Checks - CHK_SingleSet.Checked = sw.SingleSet == (sw.SinglePast / 7 + 1); + CHK_SingleSet.Checked = sw.SingleSet == ((sw.SinglePast / 7) + 1); L_SinglePast.Text = CHK_SingleSet.Checked ? "Current" : "Past"; - CHK_DoubleSet.Checked = sw.DoubleSet == (sw.DoublePast / 7 + 1); + CHK_DoubleSet.Checked = sw.DoubleSet == ((sw.DoublePast / 7) + 1); L_DoublePast.Text = CHK_DoubleSet.Checked ? "Current" : "Past"; - CHK_MultiNPCSet.Checked = sw.MultiNPCSet == (sw.MultiNPCPast / 7 + 1); + CHK_MultiNPCSet.Checked = sw.MultiNPCSet == ((sw.MultiNPCPast / 7) + 1); L_MultiNpcPast.Text = CHK_MultiNPCSet.Checked ? "Current" : "Past"; - CHK_MultiFriendsSet.Checked = sw.MultiFriendsSet == (sw.MultiFriendsPast / 7 + 1); + CHK_MultiFriendsSet.Checked = sw.MultiFriendsSet == ((sw.MultiFriendsPast / 7) + 1); L_MultiFriendsPast.Text = CHK_MultiFriendsSet.Checked ? "Current" : "Past"; - CHK_SuperSingleSet.Checked = sw.SuperSingleSet == (sw.SuperSinglePast / 7 + 1); + CHK_SuperSingleSet.Checked = sw.SuperSingleSet == ((sw.SuperSinglePast / 7) + 1); L_SSinglePast.Text = CHK_SuperSingleSet.Checked ? "Current" : "Past"; - CHK_SuperDoubleSet.Checked = sw.SuperDoubleSet == (sw.SuperDoublePast / 7 + 1); + CHK_SuperDoubleSet.Checked = sw.SuperDoubleSet == ((sw.SuperDoublePast / 7) + 1); L_SDoublePast.Text = CHK_SuperDoubleSet.Checked ? "Current" : "Past"; - CHK_SuperMultiNPCSet.Checked = sw.SuperMultiNPCSet == (sw.SuperMultiNPCPast / 7 + 1); + CHK_SuperMultiNPCSet.Checked = sw.SuperMultiNPCSet == ((sw.SuperMultiNPCPast / 7) + 1); L_SMultiNpcPast.Text = CHK_SuperMultiNPCSet.Checked ? "Current" : "Past"; - CHK_SuperMultiFriendsSet.Checked = sw.SuperMultiFriendsSet == (sw.SuperMultiFriendsPast / 7 + 1); + CHK_SuperMultiFriendsSet.Checked = sw.SuperMultiFriendsSet == ((sw.SuperMultiFriendsPast / 7) + 1); L_SMultiFriendsPast.Text = CHK_SuperMultiFriendsSet.Checked ? "Current" : "Past"; // Normal @@ -793,14 +793,14 @@ private void SaveSubway() sw.SuperMultiFriendsRecord = (int)NUD_SMultiFriendsRecord.Value; // Current Run Checks - sw.SingleSet = (CHK_SingleSet.Checked ? sw.SinglePast / 7 + 1 : 0); - sw.DoubleSet = (CHK_DoubleSet.Checked ? sw.DoublePast / 7 + 1 : 0); - sw.MultiNPCSet = (CHK_MultiNPCSet.Checked ? sw.MultiNPCPast / 7 + 1 : 0); - sw.MultiFriendsSet = (CHK_MultiFriendsSet.Checked ? sw.MultiFriendsPast / 7 + 1 : 0); - sw.SuperSingleSet = (CHK_SuperSingleSet.Checked ? sw.SuperSinglePast / 7 + 1 : 0); - sw.SuperDoubleSet = (CHK_SuperDoubleSet.Checked ? sw.SuperDoublePast / 7 + 1 : 0); - sw.SuperMultiNPCSet = (CHK_SuperMultiNPCSet.Checked ? sw.SuperMultiNPCPast / 7 + 1 : 0); - sw.SuperMultiFriendsSet = (CHK_SuperMultiFriendsSet.Checked ? sw.SuperMultiFriendsPast / 7 + 1 : 0); + sw.SingleSet = (CHK_SingleSet.Checked ? (sw.SinglePast / 7) + 1 : 0); + sw.DoubleSet = (CHK_DoubleSet.Checked ? (sw.DoublePast / 7) + 1 : 0); + sw.MultiNPCSet = (CHK_MultiNPCSet.Checked ? (sw.MultiNPCPast / 7) + 1 : 0); + sw.MultiFriendsSet = (CHK_MultiFriendsSet.Checked ? (sw.MultiFriendsPast / 7) + 1 : 0); + sw.SuperSingleSet = (CHK_SuperSingleSet.Checked ? (sw.SuperSinglePast / 7) + 1 : 0); + sw.SuperDoubleSet = (CHK_SuperDoubleSet.Checked ? (sw.SuperDoublePast / 7) + 1 : 0); + sw.SuperMultiNPCSet = (CHK_SuperMultiNPCSet.Checked ? (sw.SuperMultiNPCPast / 7) + 1 : 0); + sw.SuperMultiFriendsSet = (CHK_SuperMultiFriendsSet.Checked ? (sw.SuperMultiFriendsPast / 7) + 1 : 0); } private const string ForestCityBinFilter = "Forest City Bin|*.fc5"; diff --git a/PKHeX.WinForms/Util/WinFormsUtil.cs b/PKHeX.WinForms/Util/WinFormsUtil.cs index adeea5e3b..4f3b14c88 100644 --- a/PKHeX.WinForms/Util/WinFormsUtil.cs +++ b/PKHeX.WinForms/Util/WinFormsUtil.cs @@ -264,7 +264,6 @@ public static bool OpenSAVPKMDialog(IEnumerable extensions, out string? var sb = new StringBuilder(128); foreach (var type in extensions) sb.Append($"*.{type};"); - sb.Append("*.pk"); string supported = sb.ToString(); using var ofd = new OpenFileDialog(); @@ -275,23 +274,7 @@ public static bool OpenSAVPKMDialog(IEnumerable extensions, out string? "|Binary File|*.bin" + "|Backup File|*.bak"; - // Detect main - SaveFile? sav = null; - if (DetectSaveFileOnFileOpen) - { - try - { - sav = SaveFinder.FindMostRecentSaveFile(); - } - catch (Exception ex) - { - Error(ex.Message); - } - } - - if (sav != null) - ofd.FileName = sav.Metadata.FileName; - + ofd.FileName = SuggestInitialFileName(); if (ofd.ShowDialog() != DialogResult.OK) { path = null; @@ -302,6 +285,23 @@ public static bool OpenSAVPKMDialog(IEnumerable extensions, out string? return true; } + private static string? SuggestInitialFileName() + { + if (DetectSaveFileOnFileOpen) + { + try + { + var sav = SaveFinder.FindMostRecentSaveFile(); + return sav?.Metadata.FilePath; + } + catch (Exception ex) + { + Error(ex.Message); + } + } + return null; + } + /// /// Opens a dialog to save a file. /// @@ -312,7 +312,7 @@ public static bool SavePKMDialog(PKM pk) string pkx = pk.Extension; bool allowEncrypted = pk.Format >= 3 && pkx.StartsWith('p'); var genericFilter = $"Decrypted PKM File|*.{pkx}" + - (allowEncrypted ? $"|Encrypted PKM File|*.e{pkx[1..]}" : string.Empty) + + (allowEncrypted ? $"|Encrypted PKM File|*.e{pkx.AsSpan(1)}" : string.Empty) + "|Binary File|*.bin" + "|All Files|*.*"; using var sfd = new SaveFileDialog(); @@ -326,11 +326,11 @@ public static bool SavePKMDialog(PKM pk) return true; } - private static void SavePKM(PKM pk, string path, string pkx) + private static void SavePKM(PKM pk, string path, ReadOnlySpan pkx) { SaveBackup(path); - string ext = Path.GetExtension(path); - var data = $".{pkx}" == ext ? pk.DecryptedPartyData : pk.EncryptedPartyData; + var ext = Path.GetExtension(path); + var data = ext == $".{pkx}" ? pk.DecryptedPartyData : pk.EncryptedPartyData; File.WriteAllBytes(path, data); }