Minor clean

This commit is contained in:
Kurt
2025-04-13 11:55:20 -05:00
parent 1914c482c6
commit 8a19968321
11 changed files with 86 additions and 67 deletions

View File

@@ -127,36 +127,23 @@ public static byte GetGeneration(this GameVersion game)
/// </summary>
/// <param name="game">Game to retrieve the generation for</param>
/// <returns>Generation ID</returns>
public static ushort GetMaxSpeciesID(this GameVersion game)
public static ushort GetMaxSpeciesID(this GameVersion game) => game switch
{
if (Gen1.Contains(game)) return Legal.MaxSpeciesID_1;
if (Gen2.Contains(game)) return Legal.MaxSpeciesID_2;
if (Gen3.Contains(game)) return Legal.MaxSpeciesID_3;
if (Gen4.Contains(game)) return Legal.MaxSpeciesID_4;
if (Gen5.Contains(game)) return Legal.MaxSpeciesID_5;
if (Gen6.Contains(game)) return Legal.MaxSpeciesID_6;
if (Gen7b.Contains(game)) return Legal.MaxSpeciesID_7b;
if (Gen7.Contains(game))
{
if (SM.Contains(game))
return Legal.MaxSpeciesID_7;
if (USUM.Contains(game))
return Legal.MaxSpeciesID_7_USUM;
return Legal.MaxSpeciesID_7_USUM;
}
if (PLA == game) return Legal.MaxSpeciesID_8a;
if (BDSP.Contains(game)) return Legal.MaxSpeciesID_8b;
if (Gen8.Contains(game)) return Legal.MaxSpeciesID_8;
if (Gen9.Contains(game)) return Legal.MaxSpeciesID_9;
return 0;
}
/// <summary>
/// Checks if the <see cref="g1"/> version (or subset versions) is equivalent to <see cref="g2"/>.
/// </summary>
/// <param name="g1">Version (set)</param>
/// <param name="g2">Individual version</param>
public static bool Contains(this GameVersion g1, int g2) => g1.Contains((GameVersion) g2);
RD or GN or BU or YW => Legal.MaxSpeciesID_1,
GD or SI or C => Legal.MaxSpeciesID_2,
S or R or E or FR or LG or CXD => Legal.MaxSpeciesID_3,
D or P or Pt or HG or SS => Legal.MaxSpeciesID_4,
B or W or B2 or W2 => Legal.MaxSpeciesID_5,
X or Y or AS or OR => Legal.MaxSpeciesID_6,
GP or GE => Legal.MaxSpeciesID_7b,
SN or MN => Legal.MaxSpeciesID_7,
US or UM => Legal.MaxSpeciesID_7_USUM,
PLA => Legal.MaxSpeciesID_8a,
BD or SP => Legal.MaxSpeciesID_8b,
SW or SH => Legal.MaxSpeciesID_8,
SL or VL => Legal.MaxSpeciesID_9,
_ => 0
};
/// <summary>
/// Checks if the <see cref="g1"/> version (or subset versions) is equivalent to <see cref="g2"/>.
@@ -172,6 +159,17 @@ public static bool Contains(this GameVersion g1, GameVersion g2)
return g1.ContainsFromLumped(g2);
}
public static bool IsGen1(this GameVersion version) => version is RD or GN or BU or YW;
public static bool IsGen2(this GameVersion version) => version is GD or SI or C;
public static bool IsGen3(this GameVersion version) => version is S or R or E or FR or LG or CXD;
public static bool IsGen4(this GameVersion version) => version is HG or SS or D or P or Pt;
public static bool IsGen5(this GameVersion version) => version is W or B or W2 or B2;
public static bool IsGen6(this GameVersion version) => version is X or Y or AS or OR;
public static bool IsGen7(this GameVersion version) => version is SN or MN or US or UM;
public static bool IsGen7b(this GameVersion version) => version is GP or GE;
public static bool IsGen8(this GameVersion version) => version is SW or SH or PLA or BD or SP;
public static bool IsGen9(this GameVersion version) => version is SL or VL;
/// <summary>
/// Checks if the <see cref="lump"/> version is the lump of the requested saved <see cref="version"/>.
/// </summary>

View File

@@ -5,9 +5,16 @@
namespace PKHeX.Core;
internal static class Encounters8Nest
/// <summary>
/// Logic for Generation 8 Nest Encounters.
/// </summary>
public static class Encounters8Nest
{
internal static ReadOnlySpan<byte> GetNestLocations(byte loc) => loc switch
/// <summary>
/// Get the locations for a given nest index.
/// </summary>
/// <returns></returns>
public static ReadOnlySpan<byte> GetNestLocations(byte nestIndex) => nestIndex switch
{
000 => [144, 134, 122], // 000 : Stony Wilderness, South Lake Miloch, Rolling Fields
001 => [144, 126], // 001 : Stony Wilderness, Watchtower Ruins
@@ -214,18 +221,22 @@ internal static class Encounters8Nest
/// <summary>
/// Location IDs containing Dens that cannot be accessed without Rotom Bike's Water Mode.
/// </summary>
internal static ReadOnlySpan<byte> InaccessibleRank12DistributionLocations => [154,178,186,188,190,192,194,226,228,230,234]; // Areas that are entirely restricted to water
public static ReadOnlySpan<byte> InaccessibleRank12DistributionLocations => [154,178,186,188,190,192,194,226,228,230,234]; // Areas that are entirely restricted to water
/// <summary>
/// Location IDs containing Dens that cannot be accessed without Rotom Bike's Water Mode.
/// </summary>
internal static bool IsInaccessibleRank12Nest(byte nestID, byte location)
public static bool IsInaccessibleRank12Nest(byte nestID, byte location)
{
var noNest = GetInaccessibleRank12Nests(location);
return noNest.Length != 0 && noNest.Contains(nestID);
}
private static ReadOnlySpan<byte> GetInaccessibleRank12Nests(byte location) => location switch
/// <summary>
/// Returns the list of Nests that cannot be accessed without Rotom Bike's Water Mode.
/// </summary>
/// <param name="location">Met location</param>
public static ReadOnlySpan<byte> GetInaccessibleRank12Nests(byte location) => location switch
{
128 => [6,43], // East Lake Axewell
130 => [6,41,43], // West Lake Axewell

View File

@@ -51,7 +51,7 @@ public static IEnumerable<IEncounterable> GenerateEncounters(PKM pk, ITrainerInf
/// </summary>
/// <param name="pk">Rough Pokémon data which contains the requested species, gender, and form.</param>
/// <param name="info">Trainer information of the receiver.</param>
public static void OptimizeCriteria(PKM pk, ITrainerID32 info)
public static void OptimizeCriteria(PKM pk, ITrainerID32ReadOnly info)
{
pk.ID32 = info.ID32; // Necessary for Gen2 Headbutt encounters and Honey Tree encounters
var htTrash = pk.HandlingTrainerTrash;

View File

@@ -27,16 +27,23 @@ public EncounterEnumerator2(PKM pk, EvoCriteria[] chain)
Entity = pk;
Chain = chain;
if (pk is ICaughtData2 { CaughtData: not 0 } c2)
if (pk.Korean)
return;
if (pk is not ICaughtData2 c2)
{
canOriginateCrystal = true;
hasOriginalMet = true;
met = c2.MetLocation;
return;
}
else
if (c2.CaughtData == 0)
{
canOriginateCrystal = pk is { Format: >= 7, Korean: false } || pk.CanInhabitGen1();
canOriginateCrystal = GBRestrictions.CanVisitGen1(chain[0].Species); // can visit & wipe met
return;
}
canOriginateCrystal = true;
hasOriginalMet = true;
met = c2.MetLocation;
}
readonly object IEnumerator.Current => Current;

View File

@@ -96,9 +96,10 @@ public void VerifyG1(LegalityAnalysis data)
{
// Pokémon has been traded illegally between games without evolving.
// Trade evolution species IDs for Gen1 are sequential dex numbers.
var names = ParseSettings.SpeciesStrings;
var species = enc.Species;
var evolved = ParseSettings.SpeciesStrings[species + 1];
var unevolved = ParseSettings.SpeciesStrings[species];
var evolved = names[species + 1];
var unevolved = names[species];
data.AddLine(GetInvalid(string.Format(LEvoTradeReqOutsider, unevolved, evolved)));
}
}

View File

@@ -197,7 +197,7 @@ public void VerifyVCEncounter(PKM pk, IEncounterTemplate original, EncounterTran
if (original is EncounterStatic2 { DizzyPunchEgg: true}) // Dizzy Punch Gifts
FlagIncompatibleTransferMove(pk, data.Info.Moves, 146, 2); // can't have Dizzy Punch at all
bool checkShiny = pk.VC2 || (pk.VC1 && GBRestrictions.IsTimeCapsuleTransferred(pk, data.Info.Moves, original).WasTimeCapsuleTransferred());
bool checkShiny = pk.VC2 || original.Generation == 2 || MoveInfo.IsAnyFromGeneration(2, data.Info.Moves);
if (!checkShiny)
return;

View File

@@ -46,10 +46,10 @@ public static PKM GetBlank(TypeInfo type)
public static PKM GetBlank(byte gen, GameVersion version) => gen switch
{
1 when version == GameVersion.BU => new PK1(true),
7 when GameVersion.Gen7b.Contains(version) => new PB7(),
8 when GameVersion.BDSP.Contains(version) => new PB8(),
8 when GameVersion.PLA == version => new PA8(),
1 when version is GameVersion.BU => new PK1(true),
7 when version is GameVersion.GP or GameVersion.GE => new PB7(),
8 when version is GameVersion.BD or GameVersion.SP => new PB8(),
8 when version is GameVersion.PLA => new PA8(),
_ => GetBlank(gen),
};

View File

@@ -45,6 +45,9 @@ public static class Language
private static bool HasLanguage(ReadOnlySpan<byte> permitted, byte language) => permitted.Contains(language);
/// <inheritdoc cref="GetSafeLanguage(byte, LanguageID, GameVersion)"/>
public static LanguageID GetSafeLanguage(byte generation, LanguageID prefer) => GetSafeLanguage(generation, prefer, GameVersion.Any);
/// <summary>
/// Returns the language that is safe to use for the given generation.
/// </summary>
@@ -52,11 +55,11 @@ public static class Language
/// <param name="prefer">Preferred language.</param>
/// <param name="game">Game version to check.</param>
/// <returns>Language that is safe to use for the given generation.</returns>
public static LanguageID GetSafeLanguage(byte generation, LanguageID prefer, GameVersion game = GameVersion.Any) => generation switch
public static LanguageID GetSafeLanguage(byte generation, LanguageID prefer, GameVersion game) => generation switch
{
1 when game == GameVersion.BU => Japanese,
1 => HasLanguage(Languages_3, (byte)prefer) ? prefer : SafeLanguage,
2 => HasLanguage(Languages_GB, (byte)prefer) && (prefer != Korean || game == GameVersion.C) ? prefer : SafeLanguage,
2 => HasLanguage(Languages_GB, (byte)prefer) ? prefer : SafeLanguage,
3 => HasLanguage(Languages_3 , (byte)prefer) ? prefer : SafeLanguage,
4 or 5 or 6 => HasLanguage(Languages_GB, (byte)prefer) ? prefer : SafeLanguage,
_ => HasLanguage(Languages, (byte)prefer) ? prefer : SafeLanguage,

View File

@@ -45,11 +45,11 @@ public static class PokeCrypto
// Gen7 Format is the same size as Gen6.
internal const int SIZE_8STORED = 8 + (4 * SIZE_8BLOCK); // 0x148
internal const int SIZE_8STORED = 8 + (BlockCount * SIZE_8BLOCK); // 0x148
internal const int SIZE_8PARTY = SIZE_8STORED + 0x10; // 0x158
private const int SIZE_8BLOCK = 80; // 0x50
internal const int SIZE_8ASTORED = 8 + (4 * SIZE_8ABLOCK); // 0x168
internal const int SIZE_8ASTORED = 8 + (BlockCount * SIZE_8ABLOCK); // 0x168
internal const int SIZE_8APARTY = SIZE_8ASTORED + 0x10; // 0x178
private const int SIZE_8ABLOCK = 88; // 0x58
@@ -57,6 +57,8 @@ public static class PokeCrypto
internal const int SIZE_9PARTY = SIZE_8PARTY;
private const int SIZE_9BLOCK = SIZE_8BLOCK;
private const int BlockCount = 4;
/// <summary>
/// Positions for shuffling.
/// </summary>
@@ -108,7 +110,7 @@ public static class PokeCrypto
];
/// <summary>
/// Shuffles a 232 byte array containing Pokémon data.
/// Shuffles a 4-block byte array containing Pokémon data.
/// </summary>
/// <param name="data">Data to shuffle</param>
/// <param name="sv">Block Shuffle order</param>
@@ -124,12 +126,12 @@ public static byte[] ShuffleArray(ReadOnlySpan<byte> data, uint sv, [ConstantExp
private static void ShuffleArray(ReadOnlySpan<byte> data, Span<byte> result, uint sv, [ConstantExpected(Min = 0)] int blockSize)
{
int index = (int)sv * 4;
int index = (int)sv * BlockCount;
const int start = 8;
data[..start].CopyTo(result[..start]);
var end = start + (blockSize * 4);
var end = start + (blockSize * BlockCount);
data[end..].CopyTo(result[end..]);
for (int block = 3; block >= 0; block--)
for (int block = 0; block < BlockCount; block++)
{
var dest = result.Slice(start + (blockSize * block), blockSize);
int ofs = BlockPosition[index + block];
@@ -313,7 +315,7 @@ public static byte[] EncryptArray4BE(ReadOnlySpan<byte> pk)
private static void CryptPKM(Span<byte> data, uint pv, [ConstantExpected(Min = 0)] int blockSize)
{
const int start = 8;
int end = (4 * blockSize) + start;
int end = (BlockCount * blockSize) + start;
CryptArray(data[start..end], pv); // Blocks
if (data.Length > end)
CryptArray(data[end..], pv); // Party Stats
@@ -323,7 +325,7 @@ private static void CryptPKM(Span<byte> data, uint pv, [ConstantExpected(Min = 0
private static void CryptPKM45(Span<byte> data, uint pv, uint chk, [ConstantExpected(Min = 0)] int blockSize)
{
const int start = 8;
int end = (4 * blockSize) + start;
int end = (BlockCount * blockSize) + start;
CryptArray(data[start..end], chk); // Blocks
if (data.Length > end)
CryptArray(data[end..], pv); // Party Stats
@@ -332,13 +334,13 @@ private static void CryptPKM45(Span<byte> data, uint pv, uint chk, [ConstantExpe
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CryptArray(Span<byte> data, uint seed)
{
foreach (ref var u32 in MemoryMarshal.Cast<byte, ushort>(data))
foreach (ref var u16 in MemoryMarshal.Cast<byte, ushort>(data))
{
seed = (0x41C64E6D * seed) + 0x00006073;
var xor = (ushort)(seed >> 16);
if (!BitConverter.IsLittleEndian)
xor = ReverseEndianness(xor);
u32 ^= xor;
u16 ^= xor;
}
}
@@ -382,10 +384,10 @@ private static byte[] ShuffleArray3(ReadOnlySpan<byte> data, uint sv)
private static void ShuffleArray3(ReadOnlySpan<byte> data, Span<byte> result, uint sv)
{
int index = (int)sv * 4;
int index = (int)sv * BlockCount;
data[..SIZE_3HEADER].CopyTo(result[..SIZE_3HEADER]);
data[SIZE_3STORED..].CopyTo(result[SIZE_3STORED..]);
for (int block = 3; block >= 0; block--)
for (int block = 0; block < BlockCount; block++)
{
var dest = result.Slice(SIZE_3HEADER + (SIZE_3BLOCK * block), SIZE_3BLOCK);
int ofs = BlockPosition[index + block];
@@ -418,7 +420,7 @@ public static byte[] EncryptArray3(ReadOnlySpan<byte> pk)
/// <remarks>Generation 3 Format encryption check which verifies the checksum</remarks>
public static void DecryptIfEncrypted3(ref byte[] pk)
{
ushort chk = Checksums.Add16(pk.AsSpan(0x20, 4 * SIZE_3BLOCK));
ushort chk = Checksums.Add16(pk.AsSpan(0x20, BlockCount * SIZE_3BLOCK));
if (chk != ReadUInt16LittleEndian(pk.AsSpan(0x1C)))
pk = DecryptArray3(pk);
}

View File

@@ -1,8 +1,6 @@
using Microsoft.VisualBasic.FileIO;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
namespace PKHeX.Core;
@@ -10,7 +8,7 @@ namespace PKHeX.Core;
/// <summary>
/// Base Class for Save Files
/// </summary>
public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IGeneration, IVersion, IStringConverter
public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IStringConverter, ITrainerID32
{
// General Object Properties
public byte[] Data;

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Threading;
using static System.Buffers.Binary.BinaryPrimitives;
using static PKHeX.Core.MessageStrings;
@@ -921,7 +920,7 @@ public static bool IsBackup(ReadOnlySpan<char> path)
/// Determines whether the save data size is valid for automatically detecting saves.
/// </summary>
/// <remarks>Only checks the <see cref="Handlers"/> list.</remarks>
public static bool IsSizeValidHandler(long size) => Handlers.Any(z => z.IsRecognized(size));
public static bool IsSizeValidHandler(long size) => Handlers.Exists(z => z.IsRecognized(size));
/// <summary>
/// Determines whether the save data size is valid for automatically detecting saves.