Modul 01 Hotfix A4: AnvilRecipe.IsCollectable ergänzt
01-RecipeData Rev 6 (A4) added the field as a Summarize-branch discriminator for module 02. Resolved as IsExpertRecipe OR the output item's AlwaysCollectable flag, the latter being the canonical FFXIV signal for collectable submissions (custom delivery, masterpiece supply, collectables shop). - AnvilRecipe.cs: new required bool property after CanHQ, with a why-comment pointing at module 02's Summarize branch and noting the OR-resolve. - LuminaRecipeAdapter.cs: resolve folded into the recipe walk via the same itemSheet.TryGetRow call that already fetches the display name - no bootstrap-order question, no 2-pass needed. hasOutputItem is hoisted so the OR-branch can guard against a missing item-sheet row without touching the default(Item) struct. - RecipeDataAdapterLoadStep.cs: new pass criterion #10 that asserts at least one recipe surfaces IsCollectable == true. Catches a silent resolve-path failure. Existing Cosmic-surface check shifts to #11 to keep numbering stable. Build clean (0/0), csharpier clean.
This commit is contained in:
@@ -33,6 +33,13 @@ public sealed record AnvilRecipe
|
|||||||
public required bool IsExpertRecipe { get; init; }
|
public required bool IsExpertRecipe { get; init; }
|
||||||
public required bool CanHQ { get; init; }
|
public required bool CanHQ { get; init; }
|
||||||
|
|
||||||
|
// True when the recipe is a collectable submission (custom delivery,
|
||||||
|
// masterpiece supply, collectables shop). Module 02's Summarize branch
|
||||||
|
// uses this discriminator. Resolved as IsExpertRecipe OR the output
|
||||||
|
// item's AlwaysCollectable flag - the latter is the canonical FFXIV
|
||||||
|
// signal for collectable submissions.
|
||||||
|
public required bool IsCollectable { get; init; }
|
||||||
|
|
||||||
// Cosmic Exploration (Patch 7.x). v0.1.0 ships with MissionHas* always
|
// Cosmic Exploration (Patch 7.x). v0.1.0 ships with MissionHas* always
|
||||||
// false (SH-15 option B) - the data schema stays in place so v0.2.0+ can
|
// false (SH-15 option B) - the data schema stays in place so v0.2.0+ can
|
||||||
// light up the surface by resolving the WKS mission sheet without
|
// light up the surface by resolving the WKS mission sheet without
|
||||||
|
|||||||
@@ -557,9 +557,14 @@ internal sealed class LuminaRecipeAdapter
|
|||||||
var isCosmic = recipe.Number == 0;
|
var isCosmic = recipe.Number == 0;
|
||||||
|
|
||||||
var ingredients = ResolveIngredients(recipe);
|
var ingredients = ResolveIngredients(recipe);
|
||||||
var displayName = itemSheet.TryGetRow(outputItemId, out var outputItem)
|
// IsCollectable resolves off Item.AlwaysCollectable from the same
|
||||||
? outputItem.Name.ExtractText()
|
// sheet row we already fetch for the display name. Lumina is the
|
||||||
: string.Empty;
|
// canonical source here and folding it into the Recipe walk keeps
|
||||||
|
// the adapter single-pass (the Item walk runs later and rebuilds
|
||||||
|
// its own catalog from the same sheet).
|
||||||
|
var hasOutputItem = itemSheet.TryGetRow(outputItemId, out var outputItem);
|
||||||
|
var displayName = hasOutputItem ? outputItem.Name.ExtractText() : string.Empty;
|
||||||
|
var isCollectable = recipe.IsExpert || (hasOutputItem && outputItem.AlwaysCollectable);
|
||||||
|
|
||||||
var anvilRecipe = new AnvilRecipe
|
var anvilRecipe = new AnvilRecipe
|
||||||
{
|
{
|
||||||
@@ -577,6 +582,7 @@ internal sealed class LuminaRecipeAdapter
|
|||||||
QualityForHQ = recipe.CanHq ? qualityMax : 0,
|
QualityForHQ = recipe.CanHq ? qualityMax : 0,
|
||||||
IsExpertRecipe = recipe.IsExpert,
|
IsExpertRecipe = recipe.IsExpert,
|
||||||
CanHQ = recipe.CanHq,
|
CanHQ = recipe.CanHq,
|
||||||
|
IsCollectable = isCollectable,
|
||||||
IsCosmic = isCosmic,
|
IsCosmic = isCosmic,
|
||||||
MissionHasMaterialMiracle = false,
|
MissionHasMaterialMiracle = false,
|
||||||
MissionHasSteadyHand = false,
|
MissionHasSteadyHand = false,
|
||||||
|
|||||||
@@ -157,7 +157,20 @@ internal sealed class RecipeDataAdapterLoadStep : ISelfTestStep
|
|||||||
failures++;
|
failures++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #10: Cosmic-surface sanity. v0.1.0 ships with SH-15 option B (all
|
// #10: IsCollectable sanity. FFXIV ships a non-zero number of
|
||||||
|
// collectable submission recipes (custom delivery, masterpiece
|
||||||
|
// supply, collectables shop), so the catalog must surface at
|
||||||
|
// least one. A flat false would mean the resolve path is broken.
|
||||||
|
if (!_catalog.RecipesById.Values.Any(r => r.IsCollectable))
|
||||||
|
{
|
||||||
|
_logger.LogError(
|
||||||
|
"RecipeDataCatalog.RecipesById has no recipe with "
|
||||||
|
+ "IsCollectable == true; collectable detection failed."
|
||||||
|
);
|
||||||
|
failures++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #11: Cosmic-surface sanity. v0.1.0 ships with SH-15 option B (all
|
||||||
// MissionHas* flags forced false), so the WARN is expected whenever
|
// MissionHas* flags forced false), so the WARN is expected whenever
|
||||||
// any Cosmic recipe is in the catalog. The step still returns Pass
|
// any Cosmic recipe is in the catalog. The step still returns Pass
|
||||||
// because the catalog itself is not broken - the Cosmic sub-surface
|
// because the catalog itself is not broken - the Cosmic sub-surface
|
||||||
|
|||||||
Reference in New Issue
Block a user