Add the lot ledger and mint every crafted instance through it

Quality, Ingredients and Product leave CraftedItemInstance; a unit now
carries only a LotId into the run-scoped ProvenanceLedger. ItemManager
gains the one lot-minting path (CreateLot/CreateInstance(int)), GetLot,
and Brand(), which derives a maker and product from provenance instead
of a stored field. RunSave persists the ledger pruned to what the saved
zones' entities still reach; the live ledger is never pruned, so a
floor pickup collected after a save still resolves. CopyBuild is gone:
matching hardpoints now share the same lot instead of copying values.
PropertiesPanel shows the derived brand where the design's manufacturer
used to be. AetherDb's census flags duplicate (maker, design) products
and its save command checks every crafted instance's lot against a real
run store.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-17 04:16:23 +02:00
commit 415f8e1152
13 changed files with 305 additions and 92 deletions

View file

@ -91,7 +91,8 @@ public static class Loadouts
// any failure nothing is returned and the zone and cache are unchanged, but a failed fit has already drawn from
// itemManager.Random. A design is built by its first available product in record-key order. A game spawner is to
// pass LoadoutGenerator.IsAvailable as isAvailable, with no fallback to any manufacturer. The ship always gets
// exactly WeaponGroupCount groups; a loadout with fewer is padded with empty groups.
// exactly WeaponGroupCount groups; a loadout with fewer is padded with empty groups. A failed materialization
// leaves any minted lots in the live ledger; they are not roots, so the next commit drops them.
public static Ship Materialize(ItemManager itemManager, Zone liveZone, Loadout loadout,
Predicate<FactionProductData> isAvailable, List<string> failures)
{