Fix enchanted resource IDs in recipes (T4_LEATHER_LEVEL3@3)

Enchanted refined resources are top-level items carrying their own
@enchantmentlevel, and their tradeable/market id is <name>@<n>
(e.g. T4_LEATHER_LEVEL3@3). The parser stored them — and referenced
them in enchanted recipes — as just T4_LEATHER_LEVEL3, so those inputs
never matched AODP price rows and enchanted-item costs were wrong.
Apply canonicalId(name, enchantLevel) to both item ids and craftresource
references.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Заид Омар Медхат 2026-08-23 04:59:30 +05:00
parent 742b7c2085
commit b8207f5b15

View file

@ -49,10 +49,20 @@ export interface ParseStats {
localizedNames: number; localizedNames: number;
} }
/**
* Canonical tradeable id: an item with @enchantmentlevel n>0 is `<name>@<n>`.
* This matters for enchanted refined resources, whose base names already carry
* `_LEVELn` (e.g. T4_LEATHER_LEVEL3) AND an @enchantmentlevel — the real id the
* market uses is `T4_LEATHER_LEVEL3@3`, not `T4_LEATHER_LEVEL3`.
*/
function canonicalId(uniqueName: string, enchantLevel: number | null): string {
return enchantLevel && enchantLevel > 0 ? `${uniqueName}@${enchantLevel}` : uniqueName;
}
function parseCraftResources(req: Raw): ParsedRecipe['inputs'] { function parseCraftResources(req: Raw): ParsedRecipe['inputs'] {
return asArray<Raw>(req.craftresource) return asArray<Raw>(req.craftresource)
.map((r) => ({ .map((r) => ({
item: String(r['@uniquename'] ?? ''), item: canonicalId(String(r['@uniquename'] ?? ''), num(r['@enchantmentlevel'])),
count: num(r['@count']) ?? 0, count: num(r['@count']) ?? 0,
maxReturnAmount: num(r['@maxreturnamount']), maxReturnAmount: num(r['@maxreturnamount']),
})) }))
@ -84,10 +94,15 @@ function collectItem(raw: Raw, items: ParsedItem[], recipes: ParsedRecipe[]): vo
const uniqueName = raw['@uniquename']; const uniqueName = raw['@uniquename'];
if (!uniqueName || typeof uniqueName !== 'string') return; if (!uniqueName || typeof uniqueName !== 'string') return;
// Some items (enchanted refined resources like T4_LEATHER_LEVEL3) carry their
// own @enchantmentlevel and no enchantments node — their tradeable id is @n.
const selfLevel = num(raw['@enchantmentlevel']) ?? 0;
const selfId = canonicalId(uniqueName, selfLevel);
const base: ParsedItem = { const base: ParsedItem = {
uniqueName, uniqueName: selfId,
baseName: uniqueName, baseName: uniqueName,
enchantment: 0, enchantment: selfLevel,
tier: num(raw['@tier']), tier: num(raw['@tier']),
weight: num(raw['@weight']), weight: num(raw['@weight']),
itemValue: num(raw['@itemvalue']), itemValue: num(raw['@itemvalue']),
@ -96,7 +111,7 @@ function collectItem(raw: Raw, items: ParsedItem[], recipes: ParsedRecipe[]): vo
craftingCategory: raw['@craftingcategory'] ?? null, craftingCategory: raw['@craftingcategory'] ?? null,
}; };
items.push(base); items.push(base);
recipes.push(...parseRecipesForOutput(uniqueName, raw.craftingrequirements)); recipes.push(...parseRecipesForOutput(selfId, raw.craftingrequirements));
// Enchanted variants live under enchantments.enchantment with their own recipes. // Enchanted variants live under enchantments.enchantment with their own recipes.
for (const ench of asArray<Raw>(raw.enchantments?.enchantment)) { for (const ench of asArray<Raw>(raw.enchantments?.enchantment)) {