模块:UnlockBook:修订间差异
来自星砂岛百科
更多操作
同步更新 |
同步更新 |
||
| 第5行: | 第5行: | ||
local p = {} | local p = {} | ||
local FIELD_MAP = { | |||
name = 'n', | |||
name_en = 'en', | |||
description = 'd', | |||
type_display = 'td', | |||
rarity = 'r', | |||
base_value = 'bv', | |||
sell_price = 'sp', | |||
max_stack = 'ms', | |||
origin = 'o', | |||
locked_origin = 'lo', | |||
use_description = 'u', | |||
book_family_display = 'fd', | |||
unlock_target_type_display = 'ud', | |||
unlock_target_count = 'c', | |||
unlock_station_hint = 'h', | |||
unlock_source_description = 'sd', | |||
target_keys = 'tk', | |||
station_ids = 'si', | |||
} | |||
local data_cache | local data_cache | ||
local target_cache | |||
local mapping_cache | local mapping_cache | ||
| 第17行: | 第39行: | ||
'数据:UnlockBook/unlockbook_mapping.json' | '数据:UnlockBook/unlockbook_mapping.json' | ||
) | ) | ||
target_cache = common.loadJsonData('数据:UnlockBook/unlockbook_target_index.json') or {} | |||
end | end | ||
| 第26行: | 第49行: | ||
local function get_record_from_frame(frame) | local function get_record_from_frame(frame) | ||
return find_record(common.getArg(frame, 1, '')) | return find_record(common.getArg(frame, 1, '')) | ||
end | |||
local function get_record_value(record, field) | |||
if type(record) ~= 'table' then | |||
return nil | |||
end | |||
if record[field] ~= nil then | |||
return record[field] | |||
end | |||
local mapped = FIELD_MAP[field] | |||
if mapped then | |||
return record[mapped] | |||
end | |||
return nil | |||
end | |||
local function split_target_key(target_key) | |||
local resolved = common.trim(target_key) | |||
if resolved == '' then | |||
return '', '' | |||
end | |||
local kind, target_id = mw.ustring.match(resolved, '^(.-)::(.*)$') | |||
if not kind then | |||
return '', resolved | |||
end | |||
return common.trim(kind), common.trim(target_id) | |||
end | end | ||
| 第44行: | 第93行: | ||
local output = item.renderItemWithArgs(frame, args) | local output = item.renderItemWithArgs(frame, args) | ||
return common.trim(output) ~= '' and output or '' | return common.trim(output) ~= '' and output or '' | ||
end | |||
local function resolve_target_entry(target_key) | |||
load_data() | |||
local kind, target_id = split_target_key(target_key) | |||
local target = type(target_cache) == 'table' and target_cache[target_key] or nil | |||
if type(target) ~= 'table' then | |||
return { | |||
kind = kind, | |||
id = target_id, | |||
name = target_id, | |||
item_id = '', | |||
result_count = 0, | |||
} | |||
end | |||
return { | |||
kind = kind, | |||
id = target_id, | |||
name = common.trim(target.n or target_id), | |||
item_id = common.trim(target.i or ''), | |||
result_count = tonumber(target.c or 0) or 0, | |||
} | |||
end | |||
local function get_target_entries(record) | |||
local keys = get_record_value(record, 'target_keys') | |||
if type(keys) ~= 'table' or #keys == 0 then | |||
return {} | |||
end | |||
local entries = {} | |||
for _, target_key in ipairs(keys) do | |||
local entry = resolve_target_entry(target_key) | |||
if type(entry) == 'table' then | |||
entries[#entries + 1] = entry | |||
end | |||
end | |||
return entries | |||
end | |||
local function get_station_ids(record) | |||
local station_ids = get_record_value(record, 'station_ids') | |||
if type(station_ids) ~= 'table' then | |||
return {} | |||
end | |||
return station_ids | |||
end | end | ||
local function render_plain_target(entry, show_id) | local function render_plain_target(entry, show_id) | ||
local display_name = common.trim(entry.name | local display_name = common.trim(entry.name or entry.id or '') | ||
if display_name == '' then | if display_name == '' then | ||
return '' | return '' | ||
end | end | ||
local | local text = mw.text.encode(display_name) | ||
if show_id and common.trim(entry.item_id or '') == '' then | if show_id and common.trim(entry.item_id or '') == '' then | ||
local target_id = common.trim(entry.id or '') | local target_id = common.trim(entry.id or '') | ||
| 第82行: | 第174行: | ||
end | end | ||
local function render_station_entry(frame, | local function render_station_entry(frame, station_id) | ||
local resolved_id = common.trim(station_id) | |||
if resolved_id == '' then | |||
return '' | return '' | ||
end | end | ||
local card = render_item_card(frame, resolved_id, nil, 'block') | |||
local card = render_item_card(frame, | |||
if card ~= '' then | if card ~= '' then | ||
return card | return card | ||
end | end | ||
return mw.text.encode(resolved_id) | |||
end | end | ||
| 第144行: | 第227行: | ||
if field == 'image' then | if field == 'image' then | ||
local item_id = common.trim(record | local item_id = common.trim(get_record_value(record, 'id') or '') | ||
if item_id == '' then | if item_id == '' then | ||
return '' | return '' | ||
| 第155行: | 第238行: | ||
end | end | ||
local value = record | local value = get_record_value(record, field) | ||
if type(value) == 'table' then | if type(value) == 'table' then | ||
return common.toText(value) | |||
end | end | ||
| 第172行: | 第252行: | ||
end | end | ||
local targets = record | local targets = get_target_entries(record) | ||
if | if #targets == 0 then | ||
return common.trim(record | return common.trim(get_record_value(record, 'unlock_station_hint') or '') | ||
end | end | ||
| 第182行: | 第262行: | ||
end | end | ||
local | local total_count = tonumber(get_record_value(record, 'unlock_target_count') or #targets) or #targets | ||
local more_count = math.max(total_count - 1, 0) | |||
if more_count <= 0 then | if more_count <= 0 then | ||
return with_item_css({ targets[1] }, primary) | return with_item_css({ targets[1] }, primary) | ||
| 第199行: | 第280行: | ||
end | end | ||
local targets = record | local targets = get_target_entries(record) | ||
if | if #targets == 0 then | ||
return '' | return '' | ||
end | end | ||
| 第222行: | 第303行: | ||
end | end | ||
local | local station_ids = get_station_ids(record) | ||
if | if #station_ids == 0 then | ||
return '' | return '' | ||
end | end | ||
local parts = {} | local parts = {} | ||
for _, | local entries = {} | ||
local rendered = render_station_entry(frame, | for _, station_id in ipairs(station_ids) do | ||
local rendered = render_station_entry(frame, station_id) | |||
if rendered ~= '' then | if rendered ~= '' then | ||
parts[#parts + 1] = rendered | parts[#parts + 1] = rendered | ||
entries[#entries + 1] = { | |||
id = station_id, | |||
item_id = station_id, | |||
} | |||
end | end | ||
end | end | ||
| 第238行: | 第324行: | ||
end | end | ||
return with_item_css( | return with_item_css(entries, table.concat(parts)) | ||
end | end | ||
return p | return p | ||
2026年3月17日 (二) 10:27的版本
概述
UnlockBook 提供解锁类书本条目的数据读取与展示辅助,供 Template:Infobox unlockbook 调用。
当前数据来自 `数据:UnlockBook/unlockbook_index.json` 与 `数据:UnlockBook/unlockbook_target_index.json` 两页,后者用于去重解锁目标,控制单页大小。
用法
读取字段:
{{#invoke:UnlockBook|getField|西番柿炖牛脯食谱|type_display}}
渲染主解锁对象:
{{#invoke:UnlockBook|targetSummary|西番柿炖牛脯食谱}}
渲染完整解锁清单:
{{#invoke:UnlockBook|targetList|基础建造手册}}
渲染对应设备:
{{#invoke:UnlockBook|stationList|弓箭包}}
主要函数
getField:读取基础字段。targetSummary:渲染主解锁对象摘要。targetList:渲染完整解锁清单。stationList:渲染对应设备列表。
local common = require('Module:Common')
local css = require('Module:CSS')
local item_common = require('Module:ItemCommon')
local item = require('Module:Item')
local p = {}
local FIELD_MAP = {
name = 'n',
name_en = 'en',
description = 'd',
type_display = 'td',
rarity = 'r',
base_value = 'bv',
sell_price = 'sp',
max_stack = 'ms',
origin = 'o',
locked_origin = 'lo',
use_description = 'u',
book_family_display = 'fd',
unlock_target_type_display = 'ud',
unlock_target_count = 'c',
unlock_station_hint = 'h',
unlock_source_description = 'sd',
target_keys = 'tk',
station_ids = 'si',
}
local data_cache
local target_cache
local mapping_cache
local function load_data()
if data_cache then
return
end
data_cache, mapping_cache = item_common.loadDomainData(
'数据:UnlockBook/unlockbook_index.json',
'数据:UnlockBook/unlockbook_mapping.json'
)
target_cache = common.loadJsonData('数据:UnlockBook/unlockbook_target_index.json') or {}
end
local function find_record(key)
load_data()
return item_common.findRecord(data_cache, mapping_cache, key)
end
local function get_record_from_frame(frame)
return find_record(common.getArg(frame, 1, ''))
end
local function get_record_value(record, field)
if type(record) ~= 'table' then
return nil
end
if record[field] ~= nil then
return record[field]
end
local mapped = FIELD_MAP[field]
if mapped then
return record[mapped]
end
return nil
end
local function split_target_key(target_key)
local resolved = common.trim(target_key)
if resolved == '' then
return '', ''
end
local kind, target_id = mw.ustring.match(resolved, '^(.-)::(.*)$')
if not kind then
return '', resolved
end
return common.trim(kind), common.trim(target_id)
end
local function render_item_card(frame, item_id, count, css_class)
local resolved_id = common.trim(item_id)
if resolved_id == '' then
return ''
end
local args = { resolved_id }
if count and tonumber(count) and tonumber(count) > 1 then
args[2] = tostring(count)
end
if common.trim(css_class) ~= '' then
args.class = css_class
end
local output = item.renderItemWithArgs(frame, args)
return common.trim(output) ~= '' and output or ''
end
local function resolve_target_entry(target_key)
load_data()
local kind, target_id = split_target_key(target_key)
local target = type(target_cache) == 'table' and target_cache[target_key] or nil
if type(target) ~= 'table' then
return {
kind = kind,
id = target_id,
name = target_id,
item_id = '',
result_count = 0,
}
end
return {
kind = kind,
id = target_id,
name = common.trim(target.n or target_id),
item_id = common.trim(target.i or ''),
result_count = tonumber(target.c or 0) or 0,
}
end
local function get_target_entries(record)
local keys = get_record_value(record, 'target_keys')
if type(keys) ~= 'table' or #keys == 0 then
return {}
end
local entries = {}
for _, target_key in ipairs(keys) do
local entry = resolve_target_entry(target_key)
if type(entry) == 'table' then
entries[#entries + 1] = entry
end
end
return entries
end
local function get_station_ids(record)
local station_ids = get_record_value(record, 'station_ids')
if type(station_ids) ~= 'table' then
return {}
end
return station_ids
end
local function render_plain_target(entry, show_id)
local display_name = common.trim(entry.name or entry.id or '')
if display_name == '' then
return ''
end
local text = mw.text.encode(display_name)
if show_id and common.trim(entry.item_id or '') == '' then
local target_id = common.trim(entry.id or '')
if target_id ~= '' then
text = text .. ' <span class="unlockbook-target-id"><code>' .. mw.text.encode(target_id) .. '</code></span>'
end
end
return text
end
local function render_target_entry(frame, entry, css_class, show_id)
if type(entry) ~= 'table' then
return ''
end
local count = tonumber(entry.result_count or 0) or 0
local card = render_item_card(frame, entry.item_id, count, css_class)
if card ~= '' then
return card
end
return render_plain_target(entry, show_id)
end
local function render_station_entry(frame, station_id)
local resolved_id = common.trim(station_id)
if resolved_id == '' then
return ''
end
local card = render_item_card(frame, resolved_id, nil, 'block')
if card ~= '' then
return card
end
return mw.text.encode(resolved_id)
end
local function any_item_entry(entries)
if type(entries) ~= 'table' then
return false
end
for _, entry in ipairs(entries) do
if type(entry) == 'table' and common.trim(entry.item_id or entry.id or '') ~= '' then
return true
end
end
return false
end
local function with_item_css(entries, text)
if common.trim(text) == '' then
return ''
end
if any_item_entry(entries) then
return (css.quickCall('Item') or '') .. text
end
return text
end
function p.findRecord(key)
return find_record(key)
end
function p.getField(frame)
local key = common.getArg(frame, 1, '')
local field = common.getArg(frame, 2, '')
if field == '' then
return ''
end
local record = find_record(key)
if not record then
return ''
end
if field == 'image' then
local item_id = common.trim(get_record_value(record, 'id') or '')
if item_id == '' then
return ''
end
local image_name = item_id .. '.png'
if common.filePageExists(image_name) then
return image_name
end
return ''
end
local value = get_record_value(record, field)
if type(value) == 'table' then
return common.toText(value)
end
return common.toText(value)
end
function p.targetSummary(frame)
local record = get_record_from_frame(frame)
if not record then
return ''
end
local targets = get_target_entries(record)
if #targets == 0 then
return common.trim(get_record_value(record, 'unlock_station_hint') or '')
end
local primary = render_target_entry(frame, targets[1], 'block', false)
if primary == '' then
return ''
end
local total_count = tonumber(get_record_value(record, 'unlock_target_count') or #targets) or #targets
local more_count = math.max(total_count - 1, 0)
if more_count <= 0 then
return with_item_css({ targets[1] }, primary)
end
local out = {}
out[#out + 1] = primary
out[#out + 1] = ('<div class="unlockbook-target-summary-note">另含 %d 项</div>'):format(more_count)
return with_item_css({ targets[1] }, table.concat(out))
end
function p.targetList(frame)
local record = get_record_from_frame(frame)
if not record then
return ''
end
local targets = get_target_entries(record)
if #targets == 0 then
return ''
end
local out = {}
out[#out + 1] = '<ul class="unlockbook-target-list">'
for _, entry in ipairs(targets) do
local rendered = render_target_entry(frame, entry, 'block', true)
if rendered ~= '' then
out[#out + 1] = '<li>' .. rendered .. '</li>'
end
end
out[#out + 1] = '</ul>'
return with_item_css(targets, table.concat(out))
end
function p.stationList(frame)
local record = get_record_from_frame(frame)
if not record then
return ''
end
local station_ids = get_station_ids(record)
if #station_ids == 0 then
return ''
end
local parts = {}
local entries = {}
for _, station_id in ipairs(station_ids) do
local rendered = render_station_entry(frame, station_id)
if rendered ~= '' then
parts[#parts + 1] = rendered
entries[#entries + 1] = {
id = station_id,
item_id = station_id,
}
end
end
if #parts == 0 then
return ''
end
return with_item_css(entries, table.concat(parts))
end
return p