2017-11-09 06:59:18 +00:00
#define SUPPRESS
2017-07-18 23:21:31 +00:00
using System ;
2016-03-25 07:10:11 +00:00
using System.Collections.Generic ;
2016-03-05 04:43:00 +00:00
using System.Linq ;
2020-11-27 20:00:49 +00:00
using static PKHeX . Core . LegalityAnalyzers ;
2020-11-28 02:45:06 +00:00
using static PKHeX . Core . LegalityCheckStrings ;
using static PKHeX . Core . ParseSettings ;
2016-02-23 06:52:48 +00:00
2017-01-08 07:54:09 +00:00
namespace PKHeX.Core
2016-02-23 06:52:48 +00:00
{
2017-10-24 06:12:58 +00:00
/// <summary>
/// Legality Check object containing the <see cref="CheckResult"/> data and overview values from the parse.
/// </summary>
2020-11-27 20:00:49 +00:00
public sealed class LegalityAnalysis
2016-02-23 06:52:48 +00:00
{
2018-06-24 05:00:01 +00:00
internal readonly PKM pkm ;
2018-07-21 03:22:46 +00:00
internal readonly PersonalInfo PersonalInfo ;
2020-12-22 01:17:56 +00:00
private readonly List < CheckResult > Parse = new ( ) ;
2016-10-23 19:48:49 +00:00
2019-02-15 04:14:46 +00:00
/// <summary>
/// Parse result list allowing view of the legality parse.
/// </summary>
public IReadOnlyList < CheckResult > Results = > Parse ;
2019-11-16 01:34:18 +00:00
/// <summary>
/// Only use this when trying to mutate the legality. Not for use when checking legality.
/// </summary>
public void ResetParse ( ) = > Parse . Clear ( ) ;
2018-07-21 03:22:46 +00:00
/// <summary>
/// Matched encounter data for the <see cref="pkm"/>.
/// </summary>
2018-06-24 05:00:01 +00:00
public IEncounterable EncounterMatch = > Info . EncounterMatch ;
2018-07-21 03:22:46 +00:00
/// <summary>
/// Original encounter data for the <see cref="pkm"/>.
/// </summary>
/// <remarks>
/// Generation 1/2 <see cref="pkm"/> that are transferred forward to Generation 7 are restricted to new encounter details.
/// By retaining their original match, more information can be provided by the parse.
/// </remarks>
2019-12-09 23:48:54 +00:00
public IEncounterable EncounterOriginal = > Info . EncounterOriginal ;
2017-11-07 02:06:23 +00:00
2018-07-21 03:22:46 +00:00
/// <summary>
/// Indicates if all checks ran to completion.
/// </summary>
/// <remarks>This value is false if any checks encountered an error.</remarks>
2017-08-16 04:16:47 +00:00
public readonly bool Parsed ;
2018-07-21 03:22:46 +00:00
/// <summary>
/// Indicates if all checks returned a <see cref="Severity.Valid"/> result.
/// </summary>
2017-08-16 04:16:47 +00:00
public readonly bool Valid ;
2018-07-21 03:22:46 +00:00
/// <summary>
/// Contains various data reused for multiple checks.
/// </summary>
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 readonly LegalInfo Info ;
2018-07-21 03:22:46 +00:00
/// <summary>
/// Creates a report message with optional verbosity for in-depth analysis.
/// </summary>
/// <param name="verbose">Include all details in the parse, including valid check messages.</param>
/// <returns>Single line string</returns>
2017-06-18 01:37:19 +00:00
public string Report ( bool verbose = false ) = > verbose ? GetVerboseLegalityReport ( ) : GetLegalityReport ( ) ;
2018-07-21 03:22:46 +00:00
2017-11-07 02:06:23 +00:00
private string EncounterName
{
get
{
2018-06-01 02:49:47 +00:00
var enc = EncounterOriginal ;
2020-10-25 03:22:08 +00:00
var str = SpeciesStrings ;
var name = ( uint ) enc . Species < str . Count ? str [ enc . Species ] : enc . Species . ToString ( ) ;
return $"{enc.LongName} ({name})" ;
2017-11-07 02:06:23 +00:00
}
}
2018-07-27 02:34:27 +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
private string? EncounterLocation
2018-01-02 20:00:41 +00:00
{
get
{
2018-06-01 02:49:47 +00:00
var enc = EncounterOriginal as ILocation ;
2018-01-31 04:24:45 +00:00
return enc ? . GetEncounterLocation ( Info . Generation , pkm . Version ) ;
2018-01-02 20:00:41 +00:00
}
}
2016-03-14 03:19:04 +00:00
2017-10-24 06:12:58 +00:00
/// <summary>
2020-01-17 07:22:54 +00:00
/// Checks the input <see cref="PKM"/> data for legality. This is the best method for checking with context, as some games do not have all Alternate Form data available.
2017-10-24 06:12:58 +00:00
/// </summary>
/// <param name="pk">Input data to check</param>
2017-11-07 03:31:24 +00:00
/// <param name="table"><see cref="SaveFile"/> specific personal data</param>
2020-12-11 04:42:30 +00:00
public LegalityAnalysis ( PKM pk , PersonalTable table ) : this ( pk , table . GetFormEntry ( pk . Species , pk . Form ) ) { }
2020-01-17 07:22:54 +00:00
/// <summary>
/// Checks the input <see cref="PKM"/> data for legality.
/// </summary>
/// <param name="pk">Input data to check</param>
public LegalityAnalysis ( PKM pk ) : this ( pk , pk . PersonalInfo ) { }
/// <summary>
/// Checks the input <see cref="PKM"/> data for legality.
/// </summary>
/// <param name="pk">Input data to check</param>
/// <param name="pi">Personal info to parse with</param>
public LegalityAnalysis ( PKM pk , PersonalInfo pi )
2016-02-23 06:52:48 +00:00
{
2018-05-28 00:57:45 +00:00
pkm = pk ;
2020-01-17 07:22:54 +00:00
PersonalInfo = pi ;
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 ( pkm . Format < = 2 ) // prior to storing GameVersion
pkm . TradebackStatus = GBRestrictions . GetTradebackStatusInitial ( pkm ) ;
2017-07-18 23:21:31 +00:00
#if SUPPRESS
2016-06-30 05:59:20 +00:00
try
2017-07-18 23:21:31 +00:00
#endif
2016-06-30 05:59:20 +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
Info = EncounterFinder . FindVerifiedEncounter ( pkm ) ;
if ( ! pkm . IsOriginValid )
AddLine ( Severity . Invalid , LEncConditionBadSpecies , CheckIdentifier . GameOrigin ) ;
GetParseMethod ( ) ( ) ;
2017-02-14 06:49:32 +00:00
2019-11-26 02:32:50 +00:00
if ( Parse . Count = = 0 ) // shouldn't ever happen as at least one is yielded above.
{
AddLine ( Severity . Invalid , L_AError , CheckIdentifier . Misc ) ;
2017-12-05 04:16:54 +00:00
return ;
2019-11-26 02:32:50 +00:00
}
2017-02-14 02:06:01 +00:00
2018-05-12 15:13:39 +00:00
Valid = Parse . All ( chk = > chk . Valid )
& & Info . Moves . All ( m = > m . Valid )
2017-12-05 04:16:54 +00:00
& & Info . Relearn . All ( m = > m . Valid ) ;
2016-11-15 00:27:15 +00:00
2019-05-11 17:12:14 +00:00
if ( ! Valid & & pkm . FatefulEncounter & & Info . Relearn . Any ( chk = > ! chk . Valid ) & & EncounterMatch is EncounterInvalid )
2018-09-01 21:11:12 +00:00
AddLine ( Severity . Indeterminate , LFatefulGiftMissing , CheckIdentifier . Fateful ) ;
2019-11-26 02:32:50 +00:00
Parsed = true ;
2016-06-30 05:59:20 +00:00
}
2017-07-18 23:21:31 +00:00
#if SUPPRESS
2020-09-05 19:11:43 +00:00
// We want to swallow any error from malformed input data from the user. The Valid state is all that we really need.
#pragma warning disable CA1031 // Do not catch general exception types
2017-03-24 06:15:49 +00:00
catch ( Exception e )
2020-09-05 19:11:43 +00:00
#pragma warning restore CA1031 // Do not catch general exception types
2017-03-24 06:15:49 +00:00
{
2017-07-18 23:21:31 +00:00
System . Diagnostics . Debug . WriteLine ( e . Message ) ;
2019-11-26 02:32:50 +00:00
Info = new LegalInfo ( pkm ) ;
2017-03-24 06:15:49 +00:00
Valid = false ;
2018-09-01 21:11:12 +00:00
AddLine ( Severity . Invalid , L_AError , CheckIdentifier . Misc ) ;
2017-03-24 06:15:49 +00:00
}
2017-07-18 23:21:31 +00:00
#endif
2016-10-23 19:48:49 +00:00
}
2018-07-27 02:34:27 +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
private Action GetParseMethod ( )
2017-12-05 04:16:54 +00:00
{
2018-10-28 04:59:31 +00:00
if ( pkm . Format < = 2 ) // prior to storing GameVersion
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
return ParsePK1 ;
2020-12-11 04:42:30 +00:00
int gen = pkm . Generation ;
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 ( gen < = 0 )
gen = pkm . Format ;
return gen switch
2017-12-05 04:16:54 +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
3 = > ParsePK3 ,
4 = > ParsePK4 ,
5 = > ParsePK5 ,
6 = > ParsePK6 ,
2017-12-05 04:16:54 +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
1 = > ParsePK7 ,
2 = > ParsePK7 ,
7 = > ParsePK7 ,
2019-09-23 23:56:47 +00:00
2020-01-07 01:50:18 +00:00
8 = > ParsePK8 ,
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
_ = > throw new Exception ( )
} ;
2017-12-05 04:16:54 +00:00
}
2018-07-27 02:34:27 +00:00
2018-05-28 00:57:45 +00:00
private void ParsePK1 ( )
2017-02-13 01:00:03 +00:00
{
2017-06-18 01:37:19 +00:00
UpdateInfo ( ) ;
2018-07-25 02:33:42 +00:00
if ( pkm . TradebackStatus = = TradebackType . Any & & Info . Generation ! = pkm . Format )
pkm . TradebackStatus = TradebackType . WasTradeback ; // Example: GSC Pokemon with only possible encounters in RBY, like the legendary birds
2018-07-02 00:07:29 +00:00
Nickname . Verify ( this ) ;
Level . Verify ( this ) ;
Level . VerifyG1 ( this ) ;
2018-06-24 05:00:01 +00:00
Trainer . VerifyOTG1 ( this ) ;
2020-11-27 20:00:49 +00:00
MiscValues . VerifyMiscG1 ( this ) ;
2018-06-11 15:05:15 +00:00
if ( pkm . Format = = 2 )
2018-07-02 00:07:29 +00:00
Item . Verify ( this ) ;
2017-02-13 01:00:03 +00:00
}
2018-07-27 02:34:27 +00:00
2018-05-28 00:57:45 +00:00
private void ParsePK3 ( )
2017-03-18 23:50:34 +00:00
{
2017-06-18 01:37:19 +00:00
UpdateInfo ( ) ;
UpdateChecks ( ) ;
2017-05-28 04:17:53 +00:00
if ( pkm . Format > 3 )
2018-06-24 05:00:01 +00:00
Transfer . VerifyTransferLegalityG3 ( this ) ;
2017-04-30 19:17:27 +00:00
2018-05-28 00:57:45 +00:00
if ( pkm . Version = = ( int ) GameVersion . CXD )
2018-07-02 00:07:29 +00:00
CXD . Verify ( this ) ;
2017-06-09 03:57:30 +00:00
2020-12-22 06:33:48 +00:00
if ( Info . EncounterMatch is WC3 { NotDistributed : true } )
2018-09-01 21:11:12 +00:00
AddLine ( Severity . Invalid , LEncUnreleased , CheckIdentifier . Encounter ) ;
2019-11-17 00:05:45 +00:00
if ( pkm . Format > = 8 )
Transfer . VerifyTransferLegalityG8 ( this ) ;
2017-03-18 23:50:34 +00:00
}
2018-07-27 02:34:27 +00:00
2018-05-28 00:57:45 +00:00
private void ParsePK4 ( )
2017-03-18 23:50:34 +00:00
{
2017-06-18 01:37:19 +00:00
UpdateInfo ( ) ;
UpdateChecks ( ) ;
2017-05-28 04:17:53 +00:00
if ( pkm . Format > 4 )
2018-06-24 05:00:01 +00:00
Transfer . VerifyTransferLegalityG4 ( this ) ;
2019-11-17 00:05:45 +00:00
if ( pkm . Format > = 8 )
Transfer . VerifyTransferLegalityG8 ( this ) ;
2017-03-18 23:50:34 +00:00
}
2018-07-27 02:34:27 +00:00
2018-05-28 00:57:45 +00:00
private void ParsePK5 ( )
2017-03-18 23:50:34 +00:00
{
2017-06-18 01:37:19 +00:00
UpdateInfo ( ) ;
UpdateChecks ( ) ;
2018-07-02 00:07:29 +00:00
NHarmonia . Verify ( this ) ;
2019-11-17 00:05:45 +00:00
if ( pkm . Format > = 8 )
Transfer . VerifyTransferLegalityG8 ( this ) ;
2017-03-18 23:50:34 +00:00
}
2018-07-27 02:34:27 +00:00
2018-05-28 00:57:45 +00:00
private void ParsePK6 ( )
2016-10-23 19:48:49 +00:00
{
2017-06-18 01:37:19 +00:00
UpdateInfo ( ) ;
UpdateChecks ( ) ;
2019-11-17 00:05:45 +00:00
if ( pkm . Format > = 8 )
Transfer . VerifyTransferLegalityG8 ( this ) ;
2016-10-23 19:48:49 +00:00
}
2018-07-27 02:34:27 +00:00
2018-05-28 00:57:45 +00:00
private void ParsePK7 ( )
2016-10-23 19:48:49 +00:00
{
2017-06-18 01:37:19 +00:00
UpdateInfo ( ) ;
2017-07-09 15:47:17 +00:00
if ( pkm . VC )
UpdateVCTransferInfo ( ) ;
2017-06-18 01:37:19 +00:00
UpdateChecks ( ) ;
2019-11-17 00:05:45 +00:00
if ( pkm . Format > = 8 )
Transfer . VerifyTransferLegalityG8 ( this ) ;
2016-03-12 04:56:40 +00:00
}
2016-03-14 03:19:04 +00:00
2019-09-23 23:56:47 +00:00
private void ParsePK8 ( )
{
UpdateInfo ( ) ;
UpdateChecks ( ) ;
2019-11-28 19:51:23 +00:00
Transfer . VerifyTransferLegalityG8 ( this ) ;
2019-09-23 23:56:47 +00:00
}
2018-07-21 03:22:46 +00:00
/// <summary>
/// Adds a new Check parse value.
/// </summary>
/// <param name="s">Check severity</param>
/// <param name="c">Check comment</param>
/// <param name="i">Check type</param>
internal void AddLine ( Severity s , string c , CheckIdentifier i ) = > AddLine ( new CheckResult ( s , c , i ) ) ;
/// <summary>
/// Adds a new Check parse value.
/// </summary>
2018-07-27 02:34:27 +00:00
/// <param name="chk">Check result to add.</param>
2018-07-21 03:22:46 +00:00
internal void AddLine ( CheckResult chk ) = > Parse . Add ( chk ) ;
2017-12-12 00:01:24 +00:00
2017-07-09 15:47:17 +00:00
private void UpdateVCTransferInfo ( )
{
2019-12-09 23:48:54 +00:00
var enc = ( Info . EncounterOriginalGB = EncounterMatch ) ;
if ( enc is EncounterInvalid )
2018-06-10 07:26:33 +00:00
return ;
2020-09-05 19:11:43 +00:00
var vc = EncounterStaticGenerator . GetVCStaticTransferEncounter ( pkm , enc ) ;
Info . EncounterMatch = vc ;
2017-10-21 04:07:15 +00:00
2020-09-05 19:11:43 +00:00
foreach ( var z in Transfer . VerifyVCEncounter ( pkm , enc , vc , Info . Moves ) )
2017-07-09 15:47:17 +00:00
AddLine ( z ) ;
2019-04-04 03:13:30 +00:00
Transfer . VerifyTransferLegalityG12 ( this ) ;
2017-07-09 15:47:17 +00:00
}
2018-07-27 02:34:27 +00:00
2017-06-18 01:37:19 +00:00
private void UpdateInfo ( )
2016-03-12 04:56:40 +00:00
{
2017-06-21 00:57:23 +00:00
Parse . AddRange ( Info . Parse ) ;
2017-01-04 04:51:33 +00:00
}
2018-07-27 02:34:27 +00:00
2017-06-18 01:37:19 +00:00
private void UpdateChecks ( )
2017-02-15 01:33:57 +00:00
{
2018-07-02 00:07:29 +00:00
PIDEC . Verify ( this ) ;
Nickname . Verify ( this ) ;
2020-11-27 20:00:49 +00:00
LanguageIndex . Verify ( this ) ;
2018-07-02 00:07:29 +00:00
Trainer . Verify ( this ) ;
IndividualValues . Verify ( this ) ;
EffortValues . Verify ( this ) ;
Level . Verify ( this ) ;
Ribbon . Verify ( this ) ;
2020-11-27 20:00:49 +00:00
AbilityValues . Verify ( this ) ;
BallIndex . Verify ( this ) ;
FormValues . Verify ( this ) ;
MiscValues . Verify ( this ) ;
GenderValues . Verify ( this ) ;
2018-07-02 00:07:29 +00:00
Item . Verify ( this ) ;
2017-12-12 00:01:24 +00:00
if ( pkm . Format < = 6 & & pkm . Format > = 4 )
2020-11-27 20:00:49 +00:00
Gen4EncounterType . Verify ( this ) ; // Gen 6->7 transfer deletes encounter type data
2018-07-02 00:07:29 +00:00
2020-05-10 03:47:32 +00:00
Contest . Verify ( this ) ;
2018-07-02 00:07:29 +00:00
if ( pkm . Format < 6 )
return ;
2020-07-31 18:17:31 +00:00
if ( pkm . Format < 8 )
ConsoleRegion . Verify ( this ) ; // Gen 7->8 transfer deletes geolocation tracking data
2019-12-08 02:12:31 +00:00
History . Verify ( this ) ;
2020-08-05 05:56:55 +00:00
if ( pkm is ITrainerMemories )
Memory . Verify ( this ) ;
2019-11-26 19:01:09 +00:00
if ( pkm is ISuperTrain )
2018-11-14 03:10:31 +00:00
Medal . Verify ( this ) ;
2018-07-02 00:07:29 +00:00
2019-11-26 19:01:09 +00:00
if ( pkm . Format < 7 )
return ;
HyperTraining . Verify ( this ) ;
2020-11-27 20:00:49 +00:00
MiscValues . VerifyVersionEvolution ( this ) ;
2020-04-06 23:32:23 +00:00
if ( pkm . Format < 8 )
return ;
Mark . Verify ( this ) ;
2016-02-23 06:52:48 +00:00
}
2018-07-27 02:34:27 +00:00
2017-06-18 01:37:19 +00:00
private string GetLegalityReport ( )
2016-03-09 03:20:26 +00:00
{
2019-05-11 17:12:14 +00:00
if ( Valid )
return L_ALegal ;
2020-04-16 19:58:48 +00:00
if ( ! Parsed )
2018-09-01 21:11:12 +00:00
return L_AnalysisUnavailable ;
2018-05-12 15:13:39 +00:00
2017-04-29 22:45:21 +00:00
var lines = new List < string > ( ) ;
2017-06-21 00:57:23 +00:00
var vMoves = Info . Moves ;
var vRelearn = Info . Relearn ;
2016-03-12 04:56:40 +00:00
for ( int i = 0 ; i < 4 ; i + + )
2018-07-27 02:34:27 +00:00
{
2016-03-12 17:16:41 +00:00
if ( ! vMoves [ i ] . Valid )
2019-05-11 17:12:14 +00:00
lines . Add ( vMoves [ i ] . Format ( L_F0_M_1_2 , i + 1 ) ) ;
2018-07-27 02:34:27 +00:00
}
2017-02-13 01:00:03 +00:00
if ( pkm . Format > = 6 )
2018-07-27 02:34:27 +00:00
{
for ( int i = 0 ; i < 4 ; i + + )
{
if ( ! vRelearn [ i ] . Valid )
2019-05-11 17:12:14 +00:00
lines . Add ( vRelearn [ i ] . Format ( L_F0_RM_1_2 , i + 1 ) ) ;
2018-07-27 02:34:27 +00:00
}
}
2016-03-12 04:56:40 +00:00
2016-03-12 03:43:40 +00:00
// Build result string...
2019-05-11 17:12:14 +00:00
var outputLines = Parse . Where ( chk = > ! chk . Valid ) ;
lines . AddRange ( outputLines . Select ( chk = > chk . Format ( L_F0_1 ) ) ) ;
2016-11-08 16:43:57 +00:00
2017-04-29 22:45:21 +00:00
return string . Join ( Environment . NewLine , lines ) ;
2016-04-04 00:11:58 +00:00
}
2018-07-27 02:34:27 +00:00
2017-06-18 01:37:19 +00:00
private string GetVerboseLegalityReport ( )
2016-04-04 00:11:58 +00:00
{
2020-04-16 19:58:48 +00:00
if ( ! Parsed )
2018-09-01 21:11:12 +00:00
return L_AnalysisUnavailable ;
2017-04-29 22:45:21 +00:00
const string separator = "===" ;
2019-02-08 05:40:20 +00:00
string [ ] br = { separator , string . Empty } ;
2017-04-29 22:45:21 +00:00
var lines = new List < string > { br [ 1 ] } ;
lines . AddRange ( br ) ;
int rl = lines . Count ;
2016-04-16 18:36:01 +00:00
2017-06-21 00:57:23 +00:00
var vMoves = Info . Moves ;
var vRelearn = Info . Relearn ;
2016-04-16 18:36:01 +00:00
for ( int i = 0 ; i < 4 ; i + + )
2018-07-27 02:34:27 +00:00
{
2018-09-30 18:50:08 +00:00
var move = vMoves [ i ] ;
if ( ! move . Valid )
continue ;
2019-05-11 17:12:14 +00:00
var msg = move . Format ( L_F0_M_1_2 , i + 1 ) ;
2018-09-30 18:50:08 +00:00
if ( pkm . Format ! = move . Generation )
msg + = $" [Gen{move.Generation}]" ;
lines . Add ( msg ) ;
2018-07-27 02:34:27 +00:00
}
2017-02-13 01:00:03 +00:00
if ( pkm . Format > = 6 )
2018-07-27 02:34:27 +00:00
{
for ( int i = 0 ; i < 4 ; i + + )
{
if ( vRelearn [ i ] . Valid )
2019-09-11 05:07:50 +00:00
lines . Add ( vRelearn [ i ] . Format ( L_F0_RM_1_2 , i + 1 ) ) ;
2018-07-27 02:34:27 +00:00
}
}
2016-04-16 18:36:01 +00:00
2017-04-29 22:45:21 +00:00
if ( rl ! = lines . Count ) // move info added, break for next section
lines . Add ( br [ 1 ] ) ;
2018-05-12 15:13:39 +00:00
2018-09-01 21:11:12 +00:00
var outputLines = Parse . Where ( chk = > chk ? . Valid = = true & & chk . Comment ! = L_AValid ) . OrderBy ( chk = > chk . Judgement ) ; // Fishy sorted to top
2019-05-11 17:12:14 +00:00
lines . AddRange ( outputLines . Select ( chk = > chk . Format ( L_F0_1 ) ) ) ;
2016-12-31 01:13:22 +00:00
2017-04-29 22:45:21 +00:00
lines . AddRange ( br ) ;
2018-09-01 21:11:12 +00:00
lines . Add ( string . Format ( L_FEncounterType_0 , EncounterName ) ) ;
2018-01-02 20:00:41 +00:00
var loc = EncounterLocation ;
if ( ! string . IsNullOrEmpty ( loc ) )
2018-09-01 21:11:12 +00:00
lines . Add ( string . Format ( L_F0_1 , "Location" , loc ) ) ;
2017-09-08 06:53:12 +00:00
if ( pkm . VC )
2018-09-01 21:11:12 +00:00
lines . Add ( string . Format ( L_F0_1 , nameof ( GameVersion ) , Info . Game ) ) ;
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 ( ! Info . PIDParsed )
Info . PIDIV = MethodFinder . Analyze ( pkm ) ;
var pidiv = Info . PIDIV ;
2017-04-30 03:04:54 +00:00
{
if ( ! pidiv . NoSeed )
2018-09-01 21:11:12 +00:00
lines . Add ( string . Format ( L_FOriginSeed_0 , pidiv . OriginSeed . ToString ( "X8" ) ) ) ;
lines . Add ( string . Format ( L_FPIDType_0 , pidiv . Type ) ) ;
2017-04-30 03:04:54 +00:00
}
2017-07-12 16:02:03 +00:00
if ( ! Valid & & Info . InvalidMatches ! = null )
{
lines . Add ( "Other match(es):" ) ;
2019-03-18 05:19:37 +00:00
lines . AddRange ( Info . InvalidMatches . Select ( z = > $"{z.LongName}: {z.Reason}" ) ) ;
2017-07-12 16:02:03 +00:00
}
2018-05-12 15:13:39 +00:00
2017-06-18 01:37:19 +00:00
return GetLegalityReport ( ) + string . Join ( Environment . NewLine , lines ) ;
2016-03-09 03:20:26 +00:00
}
2016-02-23 06:52:48 +00:00
}
}