fix: resolve_locale de-dups sources and rejects malformed tables

Two silent-fail scenarios closed:
  - sources={c, c} would double-count in can_craft then partial-
    consume in craft. resolve_locale now de-duplicates by handle
    identity, preserving first-occurrence order.
  - {sink=x} without sources would wrap the table as Form-1 and
    crash deep inside inventory-list. resolve_locale now loud-
    errors with "locale table must contain 'sources' field"
    before reaching the bw-compat fallback.

Helper comment translated to English per code-language convention.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Calic
2026-06-14 19:29:46 +02:00
parent f938d11ca8
commit 357e7554a5

View File

@@ -76,9 +76,9 @@ local function shallow_copy(t)
return out
end
-- Locale-Resolver: akzeptiert entity_handle (bw-compat) ODER table
-- {sources={...}, sink=...}. Returns immer Form-2 mit validierten
-- Feldern. Loud-Error bei kaputter Form-2.
-- Locale resolver: accepts entity_handle (bw-compat) OR table
-- {sources={...}, sink=...}. Always returns Form-2 with validated
-- fields. Loud-error on malformed Form-2.
local function resolve_locale(locale, fn_name)
-- Form 2: explicit table
if type(locale) == "table" and locale.sources ~= nil then
@@ -92,7 +92,27 @@ local function resolve_locale(locale, fn_name)
"crafting.%s: locale.sink must not be nil",
fn_name), 3)
end
return locale
-- De-duplicate sources by identity, preserving first-occurrence order.
-- A caller building sources programmatically (e.g. {workbench_buffer,
-- player_backpack} where both alias the same entity) should not have
-- count_by_template double-count nor craft silent-fail.
local seen, deduped = {}, {}
for _, s in ipairs(locale.sources) do
if not seen[s] then
seen[s] = true
deduped[#deduped + 1] = s
end
end
return { sources = deduped, sink = locale.sink }
end
-- Form 2 malformed: a table that's not Form-2 (no sources key) is almost
-- certainly a caller typo. Loud-error explicitly instead of silently
-- falling through to the Form-1 bw-compat path (which would then crash
-- deep inside inventory-list with an opaque error).
if type(locale) == "table" then
error(string.format(
"crafting.%s: locale table must contain 'sources' field",
fn_name), 3)
end
-- Form 1 (bw-compat): bare entity_handle
if locale == nil then