<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://wiki.adventurestation.ru/index.php?action=history&amp;feed=atom&amp;title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C%3AGetField</id>
	<title>Модуль:GetField - История изменений</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.adventurestation.ru/index.php?action=history&amp;feed=atom&amp;title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C%3AGetField"/>
	<link rel="alternate" type="text/html" href="https://wiki.adventurestation.ru/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:GetField&amp;action=history"/>
	<updated>2026-05-04T22:47:13Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://wiki.adventurestation.ru/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:GetField&amp;diff=5223&amp;oldid=prev</id>
		<title>WikiHampter: Полностью удалено содержимое страницы</title>
		<link rel="alternate" type="text/html" href="https://wiki.adventurestation.ru/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:GetField&amp;diff=5223&amp;oldid=prev"/>
		<updated>2026-03-21T12:13:02Z</updated>

		<summary type="html">&lt;p&gt;Полностью удалено содержимое страницы&lt;/p&gt;
&lt;a href=&quot;https://wiki.adventurestation.ru/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:GetField&amp;amp;diff=5223&amp;amp;oldid=5222&quot;&gt;Внесённые изменения&lt;/a&gt;</summary>
		<author><name>WikiHampter</name></author>
	</entry>
	<entry>
		<id>https://wiki.adventurestation.ru/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:GetField&amp;diff=5222&amp;oldid=prev</id>
		<title>WikiHampter: Новая страница: «local p = {} local JsonPaths = require(&#039;Module:JsonPaths&#039;)  local function get_module_name(pagePath)     return JsonPaths.get(pagePath) end  local function load_cached_data(moduleName)     local ok, loaded = pcall(mw.loadData, moduleName)     if not ok or not loaded then         return nil     end     return loaded end  local function parse_indexed_part(part)     local key, idx = string.match(part, &quot;^(.-)%[(%d+)%]$&quot;)     if key then         return key, tonum...»</title>
		<link rel="alternate" type="text/html" href="https://wiki.adventurestation.ru/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:GetField&amp;diff=5222&amp;oldid=prev"/>
		<updated>2026-03-21T12:11:07Z</updated>

		<summary type="html">&lt;p&gt;Новая страница: «local p = {} local JsonPaths = require(&amp;#039;Module:JsonPaths&amp;#039;)  local function get_module_name(pagePath)     return JsonPaths.get(pagePath) end  local function load_cached_data(moduleName)     local ok, loaded = pcall(mw.loadData, moduleName)     if not ok or not loaded then         return nil     end     return loaded end  local function parse_indexed_part(part)     local key, idx = string.match(part, &amp;quot;^(.-)%[(%d+)%]$&amp;quot;)     if key then         return key, tonum...»&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p = {}&lt;br /&gt;
local JsonPaths = require(&amp;#039;Module:JsonPaths&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
local function get_module_name(pagePath)&lt;br /&gt;
    return JsonPaths.get(pagePath)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function load_cached_data(moduleName)&lt;br /&gt;
    local ok, loaded = pcall(mw.loadData, moduleName)&lt;br /&gt;
    if not ok or not loaded then&lt;br /&gt;
        return nil&lt;br /&gt;
    end&lt;br /&gt;
    return loaded&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function parse_indexed_part(part)&lt;br /&gt;
    local key, idx = string.match(part, &amp;quot;^(.-)%[(%d+)%]$&amp;quot;)&lt;br /&gt;
    if key then&lt;br /&gt;
        return key, tonumber(idx)&lt;br /&gt;
    end&lt;br /&gt;
    local num = tonumber(part)&lt;br /&gt;
    if num then&lt;br /&gt;
        return nil, num&lt;br /&gt;
    end&lt;br /&gt;
    return part, nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_by_path(tbl, path)&lt;br /&gt;
    if not tbl or path == &amp;quot;&amp;quot; then return nil end&lt;br /&gt;
    local cur = tbl&lt;br /&gt;
    for part in string.gmatch(path, &amp;quot;([^%.]+)&amp;quot;) do&lt;br /&gt;
        local key, idx = parse_indexed_part(part)&lt;br /&gt;
        if key and key ~= &amp;quot;&amp;quot; then&lt;br /&gt;
            if type(cur) ~= &amp;quot;table&amp;quot; then return nil end&lt;br /&gt;
            local nextCur = cur[key]&lt;br /&gt;
            if nextCur == nil then&lt;br /&gt;
                nextCur = cur[&amp;quot;!type:&amp;quot; .. key]&lt;br /&gt;
            end&lt;br /&gt;
            cur = nextCur&lt;br /&gt;
        end&lt;br /&gt;
        if idx then&lt;br /&gt;
            if type(cur) ~= &amp;quot;table&amp;quot; then return nil end&lt;br /&gt;
            cur = cur[idx]&lt;br /&gt;
        end&lt;br /&gt;
        if cur == nil then return nil end&lt;br /&gt;
    end&lt;br /&gt;
    return cur&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function format_value(v)&lt;br /&gt;
    local okJson, json = pcall(mw.text.jsonEncode, v)&lt;br /&gt;
    if okJson and json == &amp;quot;null&amp;quot; then&lt;br /&gt;
        return &amp;quot;null&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if v == nil then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local t = type(v)&lt;br /&gt;
    if t == &amp;quot;string&amp;quot; or t == &amp;quot;number&amp;quot; or t == &amp;quot;boolean&amp;quot; then&lt;br /&gt;
        return tostring(v)&lt;br /&gt;
    elseif t == &amp;quot;table&amp;quot; then&lt;br /&gt;
        local ok, json2 = pcall(mw.text.jsonEncode, v)&lt;br /&gt;
        if ok and json2 then&lt;br /&gt;
            return json2&lt;br /&gt;
        end&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        return tostring(v)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function to_nowiki(v)&lt;br /&gt;
    return &amp;quot;&amp;lt;nowiki&amp;gt;&amp;quot; .. v .. &amp;quot;&amp;lt;/nowiki&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function is_array(tbl)&lt;br /&gt;
    local max = 0&lt;br /&gt;
    local count = 0&lt;br /&gt;
    for k in pairs(tbl) do&lt;br /&gt;
        if type(k) ~= &amp;quot;number&amp;quot; then&lt;br /&gt;
            return false&lt;br /&gt;
        end&lt;br /&gt;
        if k &amp;gt; max then max = k end&lt;br /&gt;
        count = count + 1&lt;br /&gt;
    end&lt;br /&gt;
    return count &amp;gt; 0 and max == count&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function deep_copy(src)&lt;br /&gt;
    local dst = {}&lt;br /&gt;
    for k, v in pairs(src) do&lt;br /&gt;
        if type(v) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            dst[k] = deep_copy(v)&lt;br /&gt;
        else&lt;br /&gt;
            dst[k] = v&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return dst&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function deep_merge(dst, src)&lt;br /&gt;
    for k, v in pairs(src) do&lt;br /&gt;
        if type(v) == &amp;quot;table&amp;quot; and type(dst[k]) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            deep_merge(dst[k], v)&lt;br /&gt;
        elseif type(v) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            dst[k] = deep_copy(v)&lt;br /&gt;
        else&lt;br /&gt;
            dst[k] = v&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function resolve_entry(data, id)&lt;br /&gt;
    if type(data) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
        return nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if id and id ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        local direct = data[id]&lt;br /&gt;
        if direct ~= nil then&lt;br /&gt;
            return direct&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        local idsTable = data.id&lt;br /&gt;
        if type(idsTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            local specific = idsTable[id]&lt;br /&gt;
            if type(specific) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                local base = data[&amp;quot;default&amp;quot;]&lt;br /&gt;
                if type(base) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                    local merged = deep_copy(base)&lt;br /&gt;
                    deep_merge(merged, specific)&lt;br /&gt;
                    return merged&lt;br /&gt;
                end&lt;br /&gt;
                return deep_copy(specific)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local base = data[&amp;quot;default&amp;quot;]&lt;br /&gt;
    if type(base) == &amp;quot;table&amp;quot; then&lt;br /&gt;
        return deep_copy(base)&lt;br /&gt;
    end&lt;br /&gt;
    return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function collect_id_keys(data)&lt;br /&gt;
    if type(data) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
        return {}&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local idsTable = data.id&lt;br /&gt;
    local ids = {}&lt;br /&gt;
&lt;br /&gt;
    if type(idsTable) == &amp;quot;table&amp;quot; then&lt;br /&gt;
        for k in pairs(idsTable) do&lt;br /&gt;
            ids[#ids + 1] = k&lt;br /&gt;
        end&lt;br /&gt;
        return ids&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    for k in pairs(data) do&lt;br /&gt;
        if k ~= &amp;quot;default&amp;quot; and k ~= &amp;quot;id&amp;quot; then&lt;br /&gt;
            ids[#ids + 1] = k&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return ids&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function contains_target(v, target)&lt;br /&gt;
    if type(v) == &amp;quot;table&amp;quot; then&lt;br /&gt;
        if is_array(v) then&lt;br /&gt;
            for _, item in ipairs(v) do&lt;br /&gt;
                if tostring(item) == target then&lt;br /&gt;
                    return true&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            return false&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        for _, item in pairs(v) do&lt;br /&gt;
            if tostring(item) == target then&lt;br /&gt;
                return true&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        return false&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return tostring(v) == target&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function is_nonempty_value(v)&lt;br /&gt;
    if v == nil then return false end&lt;br /&gt;
    if type(v) == &amp;quot;table&amp;quot; then&lt;br /&gt;
        return next(v) ~= nil&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function find_matching_ids(idsTable, keyPath, searchValue)&lt;br /&gt;
    local target = tostring(searchValue)&lt;br /&gt;
    local matches = {}&lt;br /&gt;
&lt;br /&gt;
    for idKey, entry in pairs(idsTable) do&lt;br /&gt;
        if type(entry) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            local v = get_by_path(entry, keyPath)&lt;br /&gt;
            if v ~= nil and contains_target(v, target) then&lt;br /&gt;
                matches[#matches + 1] = idKey&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return matches&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function preprocess_or_return(frame, text)&lt;br /&gt;
    if type(frame.preprocess) == &amp;quot;function&amp;quot; then&lt;br /&gt;
        return frame:preprocess(text)&lt;br /&gt;
    end&lt;br /&gt;
    return text&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function get_field_loose(entry, fieldId)&lt;br /&gt;
    local value = entry[fieldId]&lt;br /&gt;
    if value ~= nil then return value end&lt;br /&gt;
    if fieldId == &amp;quot;&amp;quot; then return nil end&lt;br /&gt;
&lt;br /&gt;
    local first = string.sub(fieldId, 1, 1)&lt;br /&gt;
    local tail = string.sub(fieldId, 2)&lt;br /&gt;
    value = entry[string.lower(first) .. tail]&lt;br /&gt;
    if value ~= nil then return value end&lt;br /&gt;
&lt;br /&gt;
    return entry[string.upper(first) .. tail]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function apply_pattern(s, pattern, repl)&lt;br /&gt;
    if not pattern or pattern == &amp;quot;&amp;quot; or not s then&lt;br /&gt;
        return s&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local text = tostring(s)&lt;br /&gt;
    local replacement&lt;br /&gt;
    if repl and repl ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        replacement = tostring(repl)&lt;br /&gt;
        replacement = replacement:gsub(&amp;quot;\\(%d)&amp;quot;, &amp;quot;%%%1&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
        replacement = &amp;quot;%1&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local patt = pattern&lt;br /&gt;
    if not patt:find(&amp;quot;%^&amp;quot;) and not patt:find(&amp;quot;%$&amp;quot;) then&lt;br /&gt;
        patt = &amp;quot;^&amp;quot; .. patt .. &amp;quot;$&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return (text:gsub(patt, replacement))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function flatten_parts(entry)&lt;br /&gt;
    if type(entry) ~= &amp;quot;table&amp;quot; then return {} end&lt;br /&gt;
&lt;br /&gt;
    local parts = {}&lt;br /&gt;
    local function append_table_json(key, value)&lt;br /&gt;
        local ok, json = pcall(mw.text.jsonEncode, value)&lt;br /&gt;
        if ok and json then&lt;br /&gt;
            parts[#parts + 1] = key .. &amp;quot;=&amp;quot; .. to_nowiki(json)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local function walk(tbl, prefix)&lt;br /&gt;
        local keys = {}&lt;br /&gt;
        for k in pairs(tbl) do keys[#keys + 1] = k end&lt;br /&gt;
        table.sort(keys, function(a, b) return tostring(a) &amp;lt; tostring(b) end)&lt;br /&gt;
        for _, k in ipairs(keys) do&lt;br /&gt;
            local v = tbl[k]&lt;br /&gt;
            local kStr = tostring(k)&lt;br /&gt;
            local key = (prefix == &amp;quot;&amp;quot; and kStr or prefix .. &amp;quot;.&amp;quot; .. kStr)&lt;br /&gt;
            if type(v) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                if next(v) == nil then&lt;br /&gt;
                else&lt;br /&gt;
                    append_table_json(key, v)&lt;br /&gt;
                    if is_array(v) then&lt;br /&gt;
                        local first = v[1]&lt;br /&gt;
                        if type(first) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                            walk(first, key)&lt;br /&gt;
                        end&lt;br /&gt;
                    else&lt;br /&gt;
                        walk(v, key)&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            else&lt;br /&gt;
                parts[#parts + 1] = key .. &amp;quot;=&amp;quot; .. tostring(v)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    walk(entry, &amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    return parts&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function flatten_entry(entry)&lt;br /&gt;
    local parts = flatten_parts(entry)&lt;br /&gt;
    if #parts == 0 then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    return table.concat(parts, &amp;quot;|&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.findInGenerator(frame)&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local searchId = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local kind = (args[2] or &amp;quot;&amp;quot;):lower()&lt;br /&gt;
    local fieldId = args[3] or &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    if searchId == &amp;quot;&amp;quot; or fieldId == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if kind ~= &amp;quot;prototype&amp;quot; and kind ~= &amp;quot;component&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local storeName = (kind == &amp;quot;prototype&amp;quot;) and &amp;quot;prototype_store.json&amp;quot; or &amp;quot;component_store.json&amp;quot;&lt;br /&gt;
    local moduleName = get_module_name(storeName)&lt;br /&gt;
    local data = load_cached_data(moduleName)&lt;br /&gt;
    if not data then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local entry = data[searchId]&lt;br /&gt;
    if type(entry) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local value = get_field_loose(entry, fieldId)&lt;br /&gt;
    if value == nil then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local out = {}&lt;br /&gt;
    local t = type(value)&lt;br /&gt;
    if t == &amp;quot;table&amp;quot; then&lt;br /&gt;
        for _, v in ipairs(value) do&lt;br /&gt;
            out[#out + 1] = v&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        out[1] = value&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return mw.text.jsonEncode(out)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.flattenField(frame)&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local id = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local pagePath = args[2] or &amp;quot;&amp;quot;&lt;br /&gt;
    if id == &amp;quot;&amp;quot; or pagePath == &amp;quot;&amp;quot; then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local moduleName = get_module_name(pagePath)&lt;br /&gt;
    local data = load_cached_data(moduleName)&lt;br /&gt;
    if not data then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local entry = resolve_entry(data, id) or {}&lt;br /&gt;
    return flatten_entry(entry)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.get(frame)&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local id = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local pagePath = args[2] or &amp;quot;&amp;quot;&lt;br /&gt;
    local keyPath = args[3] or &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    if pagePath == &amp;quot;&amp;quot; then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local moduleName = get_module_name(pagePath)&lt;br /&gt;
    local data = load_cached_data(moduleName)&lt;br /&gt;
    if not data then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local entry = resolve_entry(data, id)&lt;br /&gt;
    if entry == nil then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    if keyPath == &amp;quot;&amp;quot; then&lt;br /&gt;
        return format_value(entry)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local value = get_by_path(entry, keyPath)&lt;br /&gt;
    return format_value(value)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.getId(frame)&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local searchValue = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local pagePath = args[2] or &amp;quot;&amp;quot;&lt;br /&gt;
    local keyPath = args[3] or &amp;quot;&amp;quot;&lt;br /&gt;
    local searchType = (args.searchType or &amp;quot;&amp;quot;):lower()&lt;br /&gt;
&lt;br /&gt;
    if searchValue == &amp;quot;&amp;quot; or pagePath == &amp;quot;&amp;quot; or keyPath == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if searchType == &amp;quot;&amp;quot; then&lt;br /&gt;
        searchType = &amp;quot;value&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local moduleName = get_module_name(pagePath)&lt;br /&gt;
    local data = load_cached_data(moduleName)&lt;br /&gt;
    if not data then return &amp;quot;[]&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local ids = collect_id_keys(data)&lt;br /&gt;
    if #ids == 0 then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local matches&lt;br /&gt;
    if searchType == &amp;quot;key&amp;quot; then&lt;br /&gt;
        local target = tostring(searchValue)&lt;br /&gt;
        matches = {}&lt;br /&gt;
        for _, idKey in ipairs(ids) do&lt;br /&gt;
            local entry = resolve_entry(data, idKey)&lt;br /&gt;
            if type(entry) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                local v = get_by_path(entry, keyPath)&lt;br /&gt;
                if type(v) == &amp;quot;table&amp;quot; and v[target] ~= nil then&lt;br /&gt;
                    matches[#matches + 1] = idKey&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        local target = tostring(searchValue)&lt;br /&gt;
        matches = {}&lt;br /&gt;
        for _, idKey in ipairs(ids) do&lt;br /&gt;
            local entry = resolve_entry(data, idKey)&lt;br /&gt;
            if type(entry) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                local v = get_by_path(entry, keyPath)&lt;br /&gt;
                if v ~= nil and contains_target(v, target) then&lt;br /&gt;
                    matches[#matches + 1] = idKey&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #matches == 0 then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local ok, json = pcall(mw.text.jsonEncode, matches)&lt;br /&gt;
    if ok and json then&lt;br /&gt;
        return json&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.getTplId(frame)&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local searchValue = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local pagePath = args[2] or &amp;quot;&amp;quot;&lt;br /&gt;
    local keyPath = args[3] or &amp;quot;&amp;quot;&lt;br /&gt;
    local tplPath = mw.text.unstripNoWiki(args[4] or &amp;quot;&amp;quot;)&lt;br /&gt;
    local searchType = (args.searchType or &amp;quot;&amp;quot;):lower()&lt;br /&gt;
&lt;br /&gt;
    if searchType == &amp;quot;&amp;quot; then&lt;br /&gt;
        searchType = &amp;quot;value&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if searchType == &amp;quot;path&amp;quot; then&lt;br /&gt;
        searchValue = &amp;quot;&amp;quot;&lt;br /&gt;
        pagePath = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
        keyPath = args[2] or &amp;quot;&amp;quot;&lt;br /&gt;
        tplPath = mw.text.unstripNoWiki(args[3] or &amp;quot;&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    if pagePath == &amp;quot;&amp;quot; or keyPath == &amp;quot;&amp;quot; or tplPath == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if searchType ~= &amp;quot;path&amp;quot; and searchValue == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local moduleName = get_module_name(pagePath)&lt;br /&gt;
    local data = load_cached_data(moduleName)&lt;br /&gt;
    if not data then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
    local ids = collect_id_keys(data)&lt;br /&gt;
    if #ids == 0 then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local matches&lt;br /&gt;
    if searchType == &amp;quot;path&amp;quot; then&lt;br /&gt;
        matches = {}&lt;br /&gt;
        for _, idKey in ipairs(ids) do&lt;br /&gt;
            local entry = resolve_entry(data, idKey)&lt;br /&gt;
            if type(entry) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                local v = get_by_path(entry, keyPath)&lt;br /&gt;
                if is_nonempty_value(v) then&lt;br /&gt;
                    matches[#matches + 1] = idKey&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    elseif searchType == &amp;quot;key&amp;quot; then&lt;br /&gt;
        local target = tostring(searchValue)&lt;br /&gt;
        matches = {}&lt;br /&gt;
        for _, idKey in ipairs(ids) do&lt;br /&gt;
            local entry = resolve_entry(data, idKey)&lt;br /&gt;
            if type(entry) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                local v = get_by_path(entry, keyPath)&lt;br /&gt;
                if type(v) == &amp;quot;table&amp;quot; and v[target] ~= nil then&lt;br /&gt;
                    matches[#matches + 1] = idKey&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        local target = tostring(searchValue)&lt;br /&gt;
        matches = {}&lt;br /&gt;
        for _, idKey in ipairs(ids) do&lt;br /&gt;
            local entry = resolve_entry(data, idKey)&lt;br /&gt;
            if type(entry) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                local v = get_by_path(entry, keyPath)&lt;br /&gt;
                if v ~= nil and contains_target(v, target) then&lt;br /&gt;
                    matches[#matches + 1] = idKey&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #matches == 0 then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local out = {}&lt;br /&gt;
    for _, idKey in ipairs(matches) do&lt;br /&gt;
        local tpl = p.getTpl({ args = { idKey, pagePath, tplPath }, data = data })&lt;br /&gt;
        if tpl ~= &amp;quot;&amp;quot; then&lt;br /&gt;
            out[#out + 1] = tpl&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #out == 0 then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local result = table.concat(out, &amp;quot; &amp;quot;)&lt;br /&gt;
    return preprocess_or_return(frame, result)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.getTpl(frame)&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local id = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local pagePath = args[2] or &amp;quot;&amp;quot;&lt;br /&gt;
    local tplPath = mw.text.unstripNoWiki(args[3] or &amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if id == &amp;quot;&amp;quot; or pagePath == &amp;quot;&amp;quot; or tplPath == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local moduleName = get_module_name(pagePath)&lt;br /&gt;
    local data = frame.data&lt;br /&gt;
    if not data then&lt;br /&gt;
        data = load_cached_data(moduleName)&lt;br /&gt;
    end&lt;br /&gt;
    if not data then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local entry = resolve_entry(data, id)&lt;br /&gt;
    local extra = flatten_entry(entry)&lt;br /&gt;
    local tplStr = &amp;quot;{{&amp;quot; .. tostring(tplPath) .. &amp;quot;|id=&amp;quot; .. tostring(id)&lt;br /&gt;
    if extra ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        tplStr = tplStr .. &amp;quot;|&amp;quot; .. extra&lt;br /&gt;
    end&lt;br /&gt;
    tplStr = tplStr .. &amp;quot;}}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return preprocess_or_return(frame, tplStr)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.getTplGenerator(frame)&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local searchId = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local kind = (args[2] or &amp;quot;&amp;quot;):lower()&lt;br /&gt;
    local generatorId = args[3] or &amp;quot;&amp;quot;&lt;br /&gt;
    local tplPath = mw.text.unstripNoWiki(args[4] or &amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if searchId == &amp;quot;&amp;quot; or generatorId == &amp;quot;&amp;quot; or tplPath == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if kind ~= &amp;quot;prototype&amp;quot; and kind ~= &amp;quot;component&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local dir = (kind == &amp;quot;prototype&amp;quot;) and &amp;quot;prototype/&amp;quot; or &amp;quot;component/&amp;quot;&lt;br /&gt;
    local pagePath = dir .. generatorId .. &amp;quot;.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local idsJson = p.findInGenerator({ args = { searchId, kind, generatorId } })&lt;br /&gt;
    local ok, ids = pcall(mw.text.jsonDecode, idsJson or &amp;quot;&amp;quot;)&lt;br /&gt;
    if not ok or type(ids) ~= &amp;quot;table&amp;quot; or #ids == 0 then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local moduleName = get_module_name(pagePath)&lt;br /&gt;
    local data = load_cached_data(moduleName)&lt;br /&gt;
    if not data then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local out = {}&lt;br /&gt;
    for _, id in ipairs(ids) do&lt;br /&gt;
        local tpl = p.getTpl({ args = { id, pagePath, tplPath }, data = data })&lt;br /&gt;
        if tpl ~= &amp;quot;&amp;quot; then&lt;br /&gt;
            out[#out + 1] = tpl&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local result = table.concat(out, &amp;quot; &amp;quot;)&lt;br /&gt;
    return preprocess_or_return(frame, result)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.flattenParams(entry)&lt;br /&gt;
    return flatten_parts(entry)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.getGenerator(frame)&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local searchId = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local kind = (args[2] or &amp;quot;&amp;quot;):lower()&lt;br /&gt;
    local generatorId = args[3] or &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    if searchId == &amp;quot;&amp;quot; or generatorId == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if kind ~= &amp;quot;prototype&amp;quot; and kind ~= &amp;quot;component&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local idsJson = p.findInGenerator({ args = { searchId, kind, generatorId } })&lt;br /&gt;
    local ok, ids = pcall(mw.text.jsonDecode, idsJson or &amp;quot;&amp;quot;)&lt;br /&gt;
    if not ok or type(ids) ~= &amp;quot;table&amp;quot; or #ids == 0 then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local okOut, outJson = pcall(mw.text.jsonEncode, ids)&lt;br /&gt;
    if okOut and outJson then&lt;br /&gt;
        return outJson&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.hasComp(frame)&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local entityId = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local compName = args[2] or &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    if entityId == &amp;quot;&amp;quot; or compName == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;false&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local moduleName = get_module_name(&amp;quot;component.json&amp;quot;)&lt;br /&gt;
    local data = load_cached_data(moduleName)&lt;br /&gt;
    if not data then&lt;br /&gt;
        return &amp;quot;false&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if type(data) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
        return &amp;quot;false&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local entry = data[entityId]&lt;br /&gt;
    if type(entry) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
        return &amp;quot;false&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local target = tostring(compName)&lt;br /&gt;
    for _, v in ipairs(entry) do&lt;br /&gt;
        if tostring(v) == target then&lt;br /&gt;
            return &amp;quot;true&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return &amp;quot;false&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.GeneratorId(frame)&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local pagePath = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local replace = mw.text.unstripNoWiki(args.replace or &amp;quot;&amp;quot;)&lt;br /&gt;
    local pattern = mw.text.unstripNoWiki(args.pattern or &amp;quot;(.*)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if pagePath == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local moduleName = get_module_name(pagePath)&lt;br /&gt;
    local data = load_cached_data(moduleName)&lt;br /&gt;
    if not data then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local idsTable = data.id&lt;br /&gt;
    if type(idsTable) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local ids = {}&lt;br /&gt;
    for k in pairs(idsTable) do&lt;br /&gt;
        ids[#ids + 1] = k&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    table.sort(ids)&lt;br /&gt;
&lt;br /&gt;
    if replace ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        local out = {}&lt;br /&gt;
        for _, id in ipairs(ids) do&lt;br /&gt;
            local text = apply_pattern(id, pattern, replace)&lt;br /&gt;
            if text ~= &amp;quot;&amp;quot; then&lt;br /&gt;
                out[#out + 1] = text&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        if #out == 0 then&lt;br /&gt;
            return &amp;quot;&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
        return preprocess_or_return(frame, table.concat(out, &amp;quot;\n&amp;quot;))&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local ok, json = pcall(mw.text.jsonEncode, ids)&lt;br /&gt;
    if ok and json then&lt;br /&gt;
        return json&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.GeneratorTplId(frame)&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local pagePath = args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local tplPath = args[2] or &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    if pagePath == &amp;quot;&amp;quot; or tplPath == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local moduleName = get_module_name(pagePath)&lt;br /&gt;
    local data = load_cached_data(moduleName)&lt;br /&gt;
    if not data then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local idsTable = data.id&lt;br /&gt;
    if type(idsTable) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local out = {}&lt;br /&gt;
&lt;br /&gt;
    for idKey in pairs(idsTable) do&lt;br /&gt;
        local tpl = p.getTpl({ args = { idKey, pagePath, tplPath }, data = data })&lt;br /&gt;
        if tpl ~= &amp;quot;&amp;quot; then&lt;br /&gt;
            out[#out + 1] = tpl&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    table.sort(out)&lt;br /&gt;
&lt;br /&gt;
    local result = table.concat(out, &amp;quot; &amp;quot;)&lt;br /&gt;
    return preprocess_or_return(frame, result)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>WikiHampter</name></author>
	</entry>
</feed>