mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 12:33:06 +00:00
907ed0b32f
tiny object, eliminate allocation for them since they're 10-16 bytes at most.
107 lines
3.7 KiB
C#
107 lines
3.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace PKHeX.Core.Bulk;
|
|
|
|
/// <summary>
|
|
/// Analyzes content within a <see cref="SaveFile"/> for overall <see cref="PKM"/> legality analysis.
|
|
/// </summary>
|
|
public sealed class BulkAnalysis
|
|
{
|
|
public readonly IReadOnlyList<SlotCache> AllData;
|
|
public readonly IReadOnlyList<LegalityAnalysis> AllAnalysis;
|
|
public readonly ITrainerInfo Trainer;
|
|
public readonly List<CheckResult> Parse = new();
|
|
public readonly Dictionary<ulong, SlotCache> Trackers = new();
|
|
public readonly bool Valid;
|
|
|
|
public readonly IBulkAnalysisSettings Settings;
|
|
private readonly bool[] CloneFlags;
|
|
|
|
/// <summary>
|
|
/// Checks if the <see cref="AllData"/> entity at <see cref="entryIndex"/> was previously marked as a clone of another index.
|
|
/// </summary>
|
|
public bool GetIsClone(int entryIndex) => CloneFlags[entryIndex];
|
|
|
|
/// <summary>
|
|
/// Marks the <see cref="AllData"/> entity at <see cref="entryIndex"/> as a clone of another index.
|
|
/// </summary>
|
|
public bool SetIsClone(int entryIndex, bool value = true) => CloneFlags[entryIndex] = value;
|
|
|
|
public BulkAnalysis(SaveFile sav, IBulkAnalysisSettings settings)
|
|
{
|
|
Trainer = sav;
|
|
Settings = settings;
|
|
var list = new List<SlotCache>(sav.BoxSlotCount + (sav.HasParty ? 6 : 0) + 5);
|
|
SlotInfoLoader.AddFromSaveFile(sav, list);
|
|
list.RemoveAll(IsEmptyData);
|
|
AllData = list;
|
|
AllAnalysis = GetIndividualAnalysis(list);
|
|
CloneFlags = new bool[AllData.Count];
|
|
|
|
ScanAll();
|
|
Valid = Parse.Count == 0 || Parse.TrueForAll(static z => z.Valid);
|
|
}
|
|
|
|
// Remove things that aren't actual stored data, or already flagged by legality checks.
|
|
private static bool IsEmptyData(SlotCache obj)
|
|
{
|
|
var pk = obj.Entity;
|
|
if ((uint)(pk.Species - 1) >= pk.MaxSpeciesID)
|
|
return true;
|
|
if (!pk.ChecksumValid)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Supported <see cref="IBulkAnalyzer"/> checkers that will be iterated through to check all entities.
|
|
/// </summary>
|
|
public static readonly List<IBulkAnalyzer> Analyzers = new()
|
|
{
|
|
new StandardCloneChecker(),
|
|
new DuplicateTrainerChecker(),
|
|
new DuplicatePIDChecker(),
|
|
new DuplicateEncryptionChecker(),
|
|
new HandlerChecker(),
|
|
new DuplicateGiftChecker(),
|
|
};
|
|
|
|
private void ScanAll()
|
|
{
|
|
foreach (var analyzer in Analyzers)
|
|
analyzer.Analyze(this);
|
|
}
|
|
|
|
private static string GetSummary(SlotCache entry) => $"[{entry.Identify()}]";
|
|
|
|
/// <summary>
|
|
/// Adds a new entry to the <see cref="Parse"/> list.
|
|
/// </summary>
|
|
public void AddLine(SlotCache first, SlotCache second, string msg, CheckIdentifier i, Severity s = Severity.Invalid)
|
|
{
|
|
var c = $"{msg}{Environment.NewLine}{GetSummary(first)}{Environment.NewLine}{GetSummary(second)}{Environment.NewLine}";
|
|
var chk = new CheckResult(s, i, c);
|
|
Parse.Add(chk);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a new entry to the <see cref="Parse"/> list.
|
|
/// </summary>
|
|
public void AddLine(SlotCache first, string msg, CheckIdentifier i, Severity s = Severity.Invalid)
|
|
{
|
|
var c = $"{msg}{Environment.NewLine}{GetSummary(first)}{Environment.NewLine}";
|
|
var chk = new CheckResult(s, i, c);
|
|
Parse.Add(chk);
|
|
}
|
|
|
|
private static IReadOnlyList<LegalityAnalysis> GetIndividualAnalysis(IReadOnlyList<SlotCache> pkms)
|
|
{
|
|
var results = new LegalityAnalysis[pkms.Count];
|
|
for (int i = 0; i < pkms.Count; i++)
|
|
results[i] = Get(pkms[i]);
|
|
return results;
|
|
}
|
|
|
|
private static LegalityAnalysis Get(SlotCache cache) => new(cache.Entity, cache.SAV.Personal, cache.Source.Origin);
|
|
}
|