Extract entity/template game presence filter

This commit is contained in:
Kurt 2025-02-23 11:25:47 -06:00
parent acfdd9bab3
commit 65df18ae66
4 changed files with 84 additions and 49 deletions

View File

@ -0,0 +1,63 @@
using System;
using static PKHeX.Core.EntityContext;
namespace PKHeX.Core.Searching;
/// <summary>
/// Logic to filter a large amount of entities depending on if they exist in a specific context.
/// </summary>
/// <remarks>
/// Pre-filtering should be done to disallow any species above the maximum for that context.
/// </remarks>
public static class EntityPresenceFilters
{
/// <summary>
/// Returns a filter that checks if the <see cref="PKM"/> can be present in a specified context.
/// </summary>
/// <param name="context">Destination context.</param>
/// <returns>Null if no filter is applicable (allow all)</returns>
public static Func<PKM, bool>? GetFilterEntity(EntityContext context) => context switch
{
// Allow if it already is that format (eager check)
Gen9 => static pk => pk is PK9 || PersonalTable.SV.IsPresentInGame(pk.Species, pk.Form),
Gen8a => static pk => pk is PA8 || PersonalTable.LA.IsPresentInGame(pk.Species, pk.Form),
Gen8b => static pk => pk is PB8 || PersonalTable.BDSP.IsPresentInGame(pk.Species, pk.Form),
Gen8 => static pk => pk is PK8 || PersonalTable.SWSH.IsPresentInGame(pk.Species, pk.Form),
_ => null,
};
/// <summary>
/// Returns a filter that checks if the <see cref="ISpeciesForm"/> can be present in a specified context.
/// </summary>
/// <param name="context">Destination context.</param>
/// <returns>Null if no filter is applicable (allow all)</returns>
public static Func<T, bool>? GetFilterGeneric<T>(EntityContext context) where T : ISpeciesForm => context switch
{
Gen9 => IsPresent<T, PersonalTable9SV>(PersonalTable.SV),
Gen8a => IsPresent<T, PersonalTable8LA>(PersonalTable.LA),
Gen8b => IsPresent<T, PersonalTable8BDSP>(PersonalTable.BDSP),
Gen8 => IsPresent<T, PersonalTable8SWSH>(PersonalTable.SWSH),
_ => null,
};
/// <summary>
/// Simple filter for Mystery Gift templates; will exclude any species not present in game, and cross-check the generation if it can be transferred in.
/// </summary>
public static Func<T, bool>? GetFilterGift<T>(EntityContext context, byte generation) where T : ISpeciesForm, IGeneration => context switch
{
Gen7b => z => z is WB7,
Gen7 => z => z is WC7 || z.Generation < 7,
_ when generation < 7 => z => z.Generation <= generation,
_ => GetFilterGeneric<T>(context),
};
private static Func<TSpecies, bool> IsPresent<TSpecies, TTable>(TTable pt)
where TSpecies : ISpeciesForm
where TTable : IPersonalTable
=> z =>
{
if (pt.IsPresentInGame(z.Species, z.Form))
return true;
return z is IEncounterFormRandom { IsRandomUnspecificForm: true } && pt.IsSpeciesInGame(z.Species);
};
}

View File

@ -27,6 +27,19 @@ public partial class SAV_Database : Form
private const int GridWidth = 6;
private const int GridHeight = 11;
private readonly PictureBox[] PKXBOXES;
private readonly string DatabasePath = Main.DatabasePath;
private List<SlotCache> Results = [];
private List<SlotCache> RawDB = [];
private int slotSelected = -1; // = null;
private Image? slotColor;
private const int RES_MIN = GridWidth * 1;
private const int RES_MAX = GridWidth * GridHeight;
private readonly string Counter;
private readonly string Viewed;
private const int MAXFORMAT = PKX.Generation;
private readonly SummaryPreviewer ShowSet = new();
public SAV_Database(PKMEditor f1, SAVEditor saveditor)
{
InitializeComponent();
@ -132,19 +145,6 @@ public SAV_Database(PKMEditor f1, SAVEditor saveditor)
Closing += (_, _) => ShowSet.Clear();
}
private readonly PictureBox[] PKXBOXES;
private readonly string DatabasePath = Main.DatabasePath;
private List<SlotCache> Results = [];
private List<SlotCache> RawDB = [];
private int slotSelected = -1; // = null;
private Image? slotColor;
private const int RES_MIN = GridWidth * 1;
private const int RES_MAX = GridWidth * GridHeight;
private readonly string Counter;
private readonly string Viewed;
private const int MAXFORMAT = PKX.Generation;
private readonly SummaryPreviewer ShowSet = new();
private void ClickView(object sender, EventArgs e)
{
var pb = WinFormsUtil.GetUnderlyingControl<PictureBox>(sender);
@ -409,7 +409,7 @@ private static List<SlotCache> LoadPKMSaves(string pkmdb, SaveFile sav, List<Sea
if (Main.Settings.EntityDb.FilterUnavailableSpecies)
{
var filter = GetFilterForSaveFile(sav);
var filter = EntityPresenceFilters.GetFilterEntity(sav.Context);
if (filter is not null)
result.RemoveAll(z => !filter(z.Entity));
}
@ -424,15 +424,6 @@ private static List<SlotCache> LoadPKMSaves(string pkmdb, SaveFile sav, List<Sea
return result;
}
private static Func<PKM, bool>? GetFilterForSaveFile(SaveFile sav) => sav switch
{
SAV8SWSH => static pk => pk is PK8 || PersonalTable.SWSH.IsPresentInGame(pk.Species, pk.Form),
SAV8BS => static pk => pk is PB8 || PersonalTable.BDSP.IsPresentInGame(pk.Species, pk.Form),
SAV8LA => static pk => pk is PA8 || PersonalTable.LA.IsPresentInGame(pk.Species, pk.Form),
SAV9SV => static pk => pk is PK9 || PersonalTable.SV.IsPresentInGame(pk.Species, pk.Form),
_ => null,
};
private static void TryAddPKMsFromSaveFilePath(ConcurrentBag<SlotCache> dbTemp, string file)
{
var sav = SaveUtil.GetVariantSAV(file);

View File

@ -265,22 +265,11 @@ private IEnumerable<IEncounterInfo> SearchDatabase(CancellationToken token)
var comparer = new ReferenceComparer<IEncounterInfo>();
results = results.Distinct(comparer); // only distinct objects
static Func<IEncounterInfo, bool> IsPresent<TTable>(TTable pt) where TTable : IPersonalTable => z =>
{
if (pt.IsPresentInGame(z.Species, z.Form))
return true;
return z is IEncounterFormRandom { IsRandomUnspecificForm: true } && pt.IsSpeciesInGame(z.Species);
};
if (Main.Settings.EncounterDb.FilterUnavailableSpecies)
{
results = SAV switch
{
SAV9SV s9 => results.Where(IsPresent(s9.Personal)),
SAV8SWSH s8 => results.Where(IsPresent(s8.Personal)),
SAV8BS b8 => results.Where(IsPresent(b8.Personal)),
SAV8LA a8 => results.Where(IsPresent(a8.Personal)),
_ => results.Where(z => z.Generation <= 7),
};
var filter = EntityPresenceFilters.GetFilterGeneric<IEncounterInfo>(SAV.Context);
if (filter != null)
results = results.Where(filter);
}
if (token.IsCancellationRequested)

View File

@ -7,6 +7,7 @@
using System.Threading.Tasks;
using System.Windows.Forms;
using PKHeX.Core;
using PKHeX.Core.Searching;
using PKHeX.Drawing.PokeSprite;
using PKHeX.WinForms.Properties;
using PKHeX.WinForms.Controls;
@ -237,24 +238,15 @@ private void ResetFilters(object sender, EventArgs e)
System.Media.SystemSounds.Asterisk.Play();
}
private static Func<MysteryGift, bool> IsPresent<TTable>(TTable pt) where TTable : IPersonalTable => z => pt.IsPresentInGame(z.Species, z.Form);
private void LoadDatabase()
{
var db = EncounterEvent.GetAllEvents();
if (Main.Settings.MysteryDb.FilterUnavailableSpecies)
{
db = SAV switch
{
SAV9SV s9 => db.Where(IsPresent(s9.Personal)),
SAV8SWSH s8 => db.Where(IsPresent(s8.Personal)),
SAV8BS b8 => db.Where(IsPresent(b8.Personal)),
SAV8LA a8 => db.Where(IsPresent(a8.Personal)),
SAV7b => db.Where(z => z is WB7),
SAV7 => db.Where(z => z.Generation < 7 || z is WC7),
_ => db.Where(z => z.Generation <= SAV.Generation),
};
var filter = EntityPresenceFilters.GetFilterGift<MysteryGift>(SAV.Context, SAV.Generation);
if (filter != null)
db = db.Where(filter);
}
RawDB = [..db];