2018-08-18 06:23:44 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics;
|
2021-01-17 08:05:07 +00:00
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2018-08-18 06:23:44 +00:00
|
|
|
|
using System.IO;
|
|
|
|
|
|
|
|
|
|
namespace PKHeX.Core
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Logic for detecting supported binary object formats.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static class FileUtil
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Attempts to get a binary object from the provided path.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="path"></param>
|
|
|
|
|
/// <param name="reference">Reference savefile used for PC Binary compatibility checks.</param>
|
|
|
|
|
/// <returns>Supported file object reference, null if none found.</returns>
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
public static object? GetSupportedFile(string path, SaveFile? reference = null)
|
2018-08-18 06:23:44 +00:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var fi = new FileInfo(path);
|
|
|
|
|
if (IsFileTooBig(fi.Length) || IsFileTooSmall(fi.Length))
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
var data = File.ReadAllBytes(path);
|
|
|
|
|
var ext = Path.GetExtension(path);
|
|
|
|
|
return GetSupportedFile(data, ext, reference);
|
|
|
|
|
}
|
2020-09-19 05:11:13 +00:00
|
|
|
|
#pragma warning disable CA1031 // Do not catch general exception types
|
|
|
|
|
// User input data can be fuzzed; if anything blows up, just fail safely.
|
2018-08-18 06:23:44 +00:00
|
|
|
|
catch (Exception e)
|
2020-09-19 05:11:13 +00:00
|
|
|
|
#pragma warning restore CA1031 // Do not catch general exception types
|
2018-08-18 06:23:44 +00:00
|
|
|
|
{
|
|
|
|
|
Debug.WriteLine(MessageStrings.MsgFileInUse);
|
|
|
|
|
Debug.WriteLine(e.Message);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Attempts to get a binary object from the provided inputs.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data">Binary data for the file.</param>
|
|
|
|
|
/// <param name="ext">File extension used as a hint.</param>
|
|
|
|
|
/// <param name="reference">Reference savefile used for PC Binary compatibility checks.</param>
|
|
|
|
|
/// <returns>Supported file object reference, null if none found.</returns>
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
public static object? GetSupportedFile(byte[] data, string ext, SaveFile? reference = null)
|
2018-08-18 06:23:44 +00:00
|
|
|
|
{
|
|
|
|
|
if (TryGetSAV(data, out var sav))
|
|
|
|
|
return sav;
|
|
|
|
|
if (TryGetMemoryCard(data, out var mc))
|
|
|
|
|
return mc;
|
|
|
|
|
if (TryGetPKM(data, out var pk, ext))
|
|
|
|
|
return pk;
|
|
|
|
|
if (TryGetPCBoxBin(data, out IEnumerable<byte[]> pks, reference))
|
|
|
|
|
return pks;
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
if (TryGetBattleVideo(data, out var bv))
|
2018-08-18 06:23:44 +00:00
|
|
|
|
return bv;
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
if (TryGetMysteryGift(data, out var g, ext))
|
2018-08-18 06:23:44 +00:00
|
|
|
|
return g;
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
if (TryGetGP1(data, out var gp))
|
2018-11-22 04:48:55 +00:00
|
|
|
|
return gp;
|
2020-11-04 04:12:42 +00:00
|
|
|
|
if (TryGetBundle(data, out var bundle))
|
|
|
|
|
return bundle;
|
2018-08-18 06:23:44 +00:00
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-19 05:11:13 +00:00
|
|
|
|
public static bool IsFileLocked(string path)
|
|
|
|
|
{
|
|
|
|
|
try { return (File.GetAttributes(path) & FileAttributes.ReadOnly) != 0; }
|
|
|
|
|
#pragma warning disable CA1031 // Do not catch general exception types
|
|
|
|
|
catch { return true; }
|
|
|
|
|
#pragma warning restore CA1031 // Do not catch general exception types
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int GetFileSize(string path)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var size = new FileInfo(path).Length;
|
|
|
|
|
if (size > int.MaxValue)
|
|
|
|
|
return -1;
|
|
|
|
|
return (int)size;
|
|
|
|
|
}
|
|
|
|
|
#pragma warning disable CA1031 // Do not catch general exception types
|
|
|
|
|
catch { return -1; } // Bad File / Locked
|
|
|
|
|
#pragma warning restore CA1031 // Do not catch general exception types
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-17 08:05:07 +00:00
|
|
|
|
private static bool TryGetGP1(byte[] data, [NotNullWhen(true)] out GP1? gp1)
|
2018-11-22 04:48:55 +00:00
|
|
|
|
{
|
|
|
|
|
gp1 = null;
|
|
|
|
|
if (data.Length != GP1.SIZE || BitConverter.ToUInt32(data, 0x28) == 0)
|
|
|
|
|
return false;
|
|
|
|
|
gp1 = new GP1(data);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-17 08:05:07 +00:00
|
|
|
|
private static bool TryGetBundle(byte[] data, [NotNullWhen(true)] out IPokeGroup? result)
|
2020-11-04 04:12:42 +00:00
|
|
|
|
{
|
|
|
|
|
result = null;
|
|
|
|
|
if (RentalTeam8.IsRentalTeam(data))
|
|
|
|
|
{
|
|
|
|
|
result = new RentalTeam8(data);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-18 06:23:44 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Checks if the length is too big to be a detectable file.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="length">File size</param>
|
|
|
|
|
public static bool IsFileTooBig(long length)
|
|
|
|
|
{
|
2020-10-10 20:14:32 +00:00
|
|
|
|
if (length <= 0x10_0000) // 1 MB
|
2018-08-18 06:23:44 +00:00
|
|
|
|
return false;
|
2020-10-10 20:14:32 +00:00
|
|
|
|
if (length > int.MaxValue)
|
|
|
|
|
return true;
|
|
|
|
|
if (SaveUtil.IsSizeValid((int)length))
|
2018-08-18 06:23:44 +00:00
|
|
|
|
return false;
|
|
|
|
|
if (SAV3GCMemoryCard.IsMemoryCardSize(length))
|
|
|
|
|
return false; // pbr/GC have size > 1MB
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Checks if the length is too small to be a detectable file.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="length">File size</param>
|
2020-09-19 05:11:13 +00:00
|
|
|
|
public static bool IsFileTooSmall(long length) => length < 0x20; // bigger than PK1
|
2018-08-18 06:23:44 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Tries to get an <see cref="SaveFile"/> object from the input parameters.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data">Binary data</param>
|
|
|
|
|
/// <param name="sav">Output result</param>
|
|
|
|
|
/// <returns>True if file object reference is valid, false if none found.</returns>
|
2021-01-17 08:05:07 +00:00
|
|
|
|
public static bool TryGetSAV(byte[] data, [NotNullWhen(true)] out SaveFile? sav)
|
2018-08-18 06:23:44 +00:00
|
|
|
|
{
|
|
|
|
|
sav = SaveUtil.GetVariantSAV(data);
|
|
|
|
|
return sav != null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Tries to get an <see cref="SAV3GCMemoryCard"/> object from the input parameters.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data">Binary data</param>
|
|
|
|
|
/// <param name="memcard">Output result</param>
|
|
|
|
|
/// <returns>True if file object reference is valid, false if none found.</returns>
|
2021-01-17 08:05:07 +00:00
|
|
|
|
public static bool TryGetMemoryCard(byte[] data, [NotNullWhen(true)] out SAV3GCMemoryCard? memcard)
|
2018-08-18 06:23:44 +00:00
|
|
|
|
{
|
|
|
|
|
if (!SAV3GCMemoryCard.IsMemoryCardSize(data))
|
|
|
|
|
{
|
|
|
|
|
memcard = null;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
memcard = new SAV3GCMemoryCard(data);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Tries to get an <see cref="PKM"/> object from the input parameters.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data">Binary data</param>
|
|
|
|
|
/// <param name="pk">Output result</param>
|
|
|
|
|
/// <param name="ext">Format hint</param>
|
|
|
|
|
/// <param name="sav">Reference savefile used for PC Binary compatibility checks.</param>
|
|
|
|
|
/// <returns>True if file object reference is valid, false if none found.</returns>
|
2021-01-17 08:05:07 +00:00
|
|
|
|
public static bool TryGetPKM(byte[] data, [NotNullWhen(true)] out PKM? pk, string ext, ITrainerInfo? sav = null)
|
2018-08-18 06:23:44 +00:00
|
|
|
|
{
|
|
|
|
|
if (ext == ".pgt") // size collision with pk6
|
|
|
|
|
{
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
pk = null;
|
2018-08-18 06:23:44 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
var format = PKX.GetPKMFormatFromExtension(ext, sav?.Generation ?? 6);
|
|
|
|
|
pk = PKMConverter.GetPKMfromBytes(data, prefer: format);
|
|
|
|
|
return pk != null;
|
|
|
|
|
}
|
2018-09-15 05:37:47 +00:00
|
|
|
|
|
2018-08-18 06:23:44 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Tries to get an <see cref="IEnumerable{T}"/> object from the input parameters.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data">Binary data</param>
|
|
|
|
|
/// <param name="pkms">Output result</param>
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
/// <param name="sav">Reference savefile used for PC Binary compatibility checks.</param>
|
2018-08-18 06:23:44 +00:00
|
|
|
|
/// <returns>True if file object reference is valid, false if none found.</returns>
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
public static bool TryGetPCBoxBin(byte[] data, out IEnumerable<byte[]> pkms, SaveFile? sav)
|
2018-08-18 06:23:44 +00:00
|
|
|
|
{
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
if (sav == null)
|
2018-08-18 06:23:44 +00:00
|
|
|
|
{
|
2020-04-16 19:58:48 +00:00
|
|
|
|
pkms = Array.Empty<byte[]>();
|
2018-08-18 06:23:44 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
var length = data.Length;
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
if (PKX.IsPKM(length / sav.SlotCount) || PKX.IsPKM(length / sav.BoxSlotCount))
|
2018-08-18 06:23:44 +00:00
|
|
|
|
{
|
2019-09-10 07:21:51 +00:00
|
|
|
|
pkms = ArrayUtil.EnumerateSplit(data, length);
|
2018-08-18 06:23:44 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-04-16 19:58:48 +00:00
|
|
|
|
pkms = Array.Empty<byte[]>();
|
2018-08-18 06:23:44 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Tries to get a <see cref="BattleVideo"/> object from the input parameters.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data">Binary data</param>
|
|
|
|
|
/// <param name="bv">Output result</param>
|
|
|
|
|
/// <returns>True if file object reference is valid, false if none found.</returns>
|
2021-01-17 08:05:07 +00:00
|
|
|
|
public static bool TryGetBattleVideo(byte[] data, [NotNullWhen(true)] out BattleVideo? bv)
|
2018-08-18 06:23:44 +00:00
|
|
|
|
{
|
|
|
|
|
bv = BattleVideo.GetVariantBattleVideo(data);
|
|
|
|
|
return bv != null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Tries to get a <see cref="MysteryGift"/> object from the input parameters.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data">Binary data</param>
|
|
|
|
|
/// <param name="mg">Output result</param>
|
|
|
|
|
/// <param name="ext">Format hint</param>
|
|
|
|
|
/// <returns>True if file object reference is valid, false if none found.</returns>
|
2021-01-17 08:05:07 +00:00
|
|
|
|
public static bool TryGetMysteryGift(byte[] data, [NotNullWhen(true)] out MysteryGift? mg, string ext)
|
2018-08-18 06:23:44 +00:00
|
|
|
|
{
|
|
|
|
|
mg = MysteryGift.GetMysteryGift(data, ext);
|
|
|
|
|
return mg != null;
|
|
|
|
|
}
|
2018-09-16 19:44:00 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a Temp location File Name for the <see cref="PKM"/>.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="pk">Data to be exported</param>
|
|
|
|
|
/// <param name="encrypt">Data is to be encrypted</param>
|
|
|
|
|
/// <returns>Path to temporary file location to write to.</returns>
|
|
|
|
|
public static string GetPKMTempFileName(PKM pk, bool encrypt)
|
|
|
|
|
{
|
|
|
|
|
string fn = pk.FileNameWithoutExtension;
|
|
|
|
|
string filename = fn + (encrypt ? $".ek{pk.Format}" : $".{pk.Extension}");
|
|
|
|
|
|
|
|
|
|
return Path.Combine(Path.GetTempPath(), Util.CleanFileName(filename));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a <see cref="PKM"/> from the provided <see cref="file"/> path, which is to be loaded to the <see cref="SaveFile"/>.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="file"><see cref="PKM"/> or <see cref="MysteryGift"/> file path.</param>
|
2020-06-17 02:46:22 +00:00
|
|
|
|
/// <param name="sav">Generation Info</param>
|
2018-09-16 19:44:00 +00:00
|
|
|
|
/// <returns>New <see cref="PKM"/> reference from the file.</returns>
|
2020-06-17 02:46:22 +00:00
|
|
|
|
public static PKM? GetSingleFromPath(string file, ITrainerInfo sav)
|
2018-09-16 19:44:00 +00:00
|
|
|
|
{
|
|
|
|
|
var fi = new FileInfo(file);
|
|
|
|
|
if (!fi.Exists)
|
|
|
|
|
return null;
|
2018-11-22 04:48:55 +00:00
|
|
|
|
if (fi.Length == GP1.SIZE && TryGetGP1(File.ReadAllBytes(file), out var gp1))
|
2021-01-17 08:05:07 +00:00
|
|
|
|
return gp1.ConvertToPB7(sav);
|
2018-09-16 19:44:00 +00:00
|
|
|
|
if (!PKX.IsPKM(fi.Length) && !MysteryGift.IsMysteryGift(fi.Length))
|
|
|
|
|
return null;
|
|
|
|
|
var data = File.ReadAllBytes(file);
|
|
|
|
|
var ext = fi.Extension;
|
|
|
|
|
var mg = MysteryGift.GetMysteryGift(data, ext);
|
2020-06-17 02:46:22 +00:00
|
|
|
|
var gift = mg?.ConvertToPKM(sav);
|
2018-09-16 19:44:00 +00:00
|
|
|
|
if (gift != null)
|
|
|
|
|
return gift;
|
2020-06-17 02:46:22 +00:00
|
|
|
|
int prefer = PKX.GetPKMFormatFromExtension(ext, sav.Generation);
|
2018-09-16 19:44:00 +00:00
|
|
|
|
return PKMConverter.GetPKMfromBytes(data, prefer: prefer);
|
|
|
|
|
}
|
2018-08-18 06:23:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|