The adapter is the only place in the plugin that touches Lumina and
Dalamud types - everything outside Anvil.RecipeData.Internal stays on
the BCL surface (Critical Boundary per 00-Anvil-Scope §3.3).
- LuminaRecipeAdapter: walks Status, CraftAction, Action, Item, ItemFood,
and Recipe + RecipeLevelTable, builds the AnvilXxx records, and
swaps the CatalogState into RecipeDataCatalog in one atomic write.
Cosmic actions normalise the Action-sheet ClassJob=-1 sentinel to
RowIdByClassJob key 0 (spec §2.3.1); the legacy ARR singletons
(Manipulation 278, Waste Not 279, Innovation 284, Waste Not II 285)
drop out via the PrimaryCostValue == 0 filter (spec §3.1 #3). The
CraftAction sheet wins the canonical icon at the CRP variant
(ClassJobId 8). Per-job rows are cross-checked for Cost, ClassJobLevel,
and Specialist consistency; mismatches log a warning.
- SH-15 option B is hard-wired: every AnvilRecipe ships with
MissionHasMaterialMiracle = false, MissionHasSteadyHand = false, and
IsSplendorCosmic = false in v0.1.0. IsCosmic is still set from
Recipe.Number == 0 so the catalog can label Cosmic recipes; the WKS
mission sheet chain is not walked. v0.2.0 will replace those constant
assignments with the resolver and the rest of the adapter stays put.
- The adapter invariant (Cosmic sub-flag implies the master IsCosmic
flag) throws on inconsistent recipe states at catalog-build time so
v0.2.0+ catches a broken WKS resolver before it corrupts the simulator.
- ItemFood walk uses ItemAction.Data[0] (48 = "well fed", 49 =
"medicated") instead of an ItemAction.Type column that does not exist
in the current Lumina schema. The bonus extractor filters
ItemFood.Params to the three crafting BaseParam ids (CP=11,
Craftsmanship=70, Control=71). Item rows are populated only for the
ItemIds that recipes / foods actually reference - no 50k-row mirror.
- AnvilStrings.resx + AnvilStrings.de.resx + AnvilStrings.Designer.cs:
Localization layer for condition display names and the SelfTest step
name. The adapter looks the condition strings up through the generated
ResourceManager so culture-switching is a no-restart change later on.
Two concerns bundled into one commit because the csharpier tool restore
reformatted four earlier files as soon as the manifest landed:
- .config/dotnet-tools.json: csharpier 1.2.6 as local tool, follows
the standard .config layout (dotnet tool restore will find it).
- Anvil/packages.lock.json: produced by dotnet restore, pinned alongside
the csproj's RestorePackagesWithLockFile=true.
- Anvil/RecipeData/RecipeDataLoadResult.cs: public record carrying the
adapter's load-pass summary (counts + duration + warnings). Surfaced
to the SelfTest step and future UI status surfaces.
- Anvil/RecipeData/RecipeDataCatalog.cs: public DI singleton with all
seven dictionary lookups, the two helper methods (ActionsForClassJob,
TryResolveActionRowId), and the four meta properties from spec §2.7.
Backed by a private CatalogState record that the adapter swaps in via
a volatile reference - readers either see the empty initial state or
the fully populated post-load snapshot, never a partial mid-build.
TryResolveActionRowId carries the Cosmic-sentinel logic so hook code
does not need to know about the CosmicOnly flag itself.
- Reformatting in AnvilAction.cs, ActionMechanicsTable.cs,
ConditionMechanicsTable.cs, and Anvil.csproj: csharpier-mandated
line-wrap / blank-line tweaks. No semantic changes.
Three game-mechanics tables for the simulator-relevant constants that the
Lumina sheets do not expose, plus the reverse name map the adapter uses
to walk the CraftAction + Action sheets.
- ActionMechanicsTable: 38 entries with Category, CP cost, durability,
efficiency, IQ-stack bonus, charges, granted buff, and flags.
Cross-checked against the spec mechanics table in 01-RecipeData.md
§2.3.2 (verified there against Artisan's RawInformation/Character/
Skills.cs). Combo-state CP costs (Standard/Advanced Touch) carry the
base value; the simulator applies the discount. TrainedEye uses
short.MaxValue as the sentinel for "fill Recipe.QualityMax in one
step"; ByregotsBlessing carries base EfficiencyQuality=100 with the
IQ multiplier added by the simulator.
- BuffMechanicsTable: 14 entries with StatusId, Icon, StackMax, Behavior,
the three duration fields (Steps / Seconds / Actions populated per
Behavior), Category, and LegacyStatusId for the older Innovation 259
and Manipulation 258 ids. Cross-checked against ffxiv-datamining
Status.csv (StatusId / Icon / StackMax) and Artisan's tooltip-derived
step durations. Expedience uses the explicit StatusId 3812 - the other
two "Expedience" rows (2712 / 3092) are non-crafting status effects
that would otherwise produce an ambiguous name match.
- ConditionMechanicsTable: 11 entries with Quality / Progress / CP /
Durability multipliers plus a BaseProbability slot. Robust mirrors
Sturdy's durability discount and keeps Quality neutral (per the
spec mechanics table - the enum doc comment in AnvilCondition.cs
predates rev 5 and is noted as superseded in the table header).
SplendorCosmic's Good=1.75 override lives in the simulator.
BaseProbability stays 0.0; the static catalog has no useful per-recipe
spawn distribution because FFXIV derives that from Recipe.IsExpert +
RecipeLevelTable.Stars at runtime.
- ActionKindByName: reverse map from English action names to
AnvilActionKind, plus the Action-sheet whitelist (seven step-counter
buff actions + two Cosmic singletons) used to filter the Action sheet
walk down to the crafting subset.
Module 01 public-API surface: six sealed records with init-only
properties plus their nine enums. All BCL-only - no Lumina or Dalamud
types in any public property, which is what keeps the simulator and
catalog xUnit-testable per the Critical Boundary in 00-Anvil-Scope §3.3.
- AnvilRecipe + AnvilRecipeIngredient: flat representation of the
Recipe + RecipeLevelTable sheet pair with the five Cosmic-Exploration
flags. v0.1.0 ships with MissionHas* always false (SH-15 option B);
the schema stays in place so v0.2.0 can wire the WKS mission sheet
without touching the type.
- AnvilItem: slim per-recipe / per-food item view (full ~50k-row item
mirror is left to the UI layer).
- AnvilAction + AnvilActionKind + AnvilActionCategory + AnvilActionFlags:
one logical action per Kind value with RowIdByClassJob mapping; Cosmic
actions use ClassJobId 0 as the sentinel for "every crafter".
AnvilActionFlags bit 1 << 2 is intentionally vacant (ConsumesGreatStrides
was removed in spec rev 5; consumption logic lives in 02-CraftingSimulator).
- AnvilBuff + AnvilBuffKind + AnvilBuffBehavior + AnvilBuffCategory:
static buff catalog entry with the duration field that matches Behavior
(Steps / Seconds / Actions). Two Cosmic buffs (MaterialMiracleBuff,
StellarSteadyHandBuff).
- AnvilCondition + AnvilConditionKind: eleven conditions including the
Cosmic Robust variant. DisplayName comes from AnvilStrings.resx, not
Lumina (the Status sheet does not expose the crafting condition labels
cleanly).
- AnvilFood + AnvilFoodBonus + AnvilFoodKind + AnvilFoodStat: ItemFood
mirror with IsRelative flag (percentage vs flat bonus).