Модуль:Entity Sprite/all: различия между версиями

Новая страница: «local p = {} -- Загрузка данных local function loadData(filePath) local page = mw.title.new(filePath) local content = page and page:getContent() return content and mw.text.jsonDecode(content) or nil end -- Проверка равенства двух таблиц local function deepEqual(t1, t2) if t1 == t2 then return true end if type(t1) ~= "table" or type(t2) ~= "table" then return false end -- Если это ма...»
 
Нет описания правки
 
(не показаны 72 промежуточные версии этого же участника)
Строка 1: Строка 1:
local p = {}
local p = {}
local JsonPaths = require('Module:JsonPaths')


-- Загрузка данных
local function normalizeSpritePath(path)
local function loadData(filePath)
if path == nil then
    local page = mw.title.new(filePath)
return nil
    local content = page and page:getContent()
end
    return content and mw.text.jsonDecode(content) or nil
 
path = mw.text.trim(tostring(path))
path = path:gsub("^/Textures/?", "")
 
return path
end
end


-- Проверка равенства двух таблиц
local function normalizeData(data)
local function deepEqual(t1, t2)
if type(data) ~= "table" then
    if t1 == t2 then return true end
return nil
    if type(t1) ~= "table" or type(t2) ~= "table" then return false end
end


    -- Если это массивы, проверяем их содержимое без учета порядка
if type(data.id) == "table" then
    local function isArray(t)
return data.id
        for _, v in pairs(t) do
end
            if type(v) == "nil" then return false end
        end
        return true
    end


    if isArray(t1) and isArray(t2) then
return data
        if #t1 ~= #t2 then return false end
end
        local matched = {}
        for _, v1 in pairs(t1) do
            local found = false
            for _, v2 in pairs(t2) do
                if not matched[v2] and deepEqual(v1, v2) then
                    matched[v2] = true
                    found = true
                    break
                end
            end
            if not found then return false end
        end
        return true
    end


    -- Если это таблицы, проверяем их содержимое
local function buildEntryKey(entry)
    for k, v in pairs(t1) do
local parts = {}
        if not deepEqual(v, t2[k]) then
            return false
        end
    end


    for k, v in pairs(t2) do
local function addField(name, value)
        if not deepEqual(v, t1[k]) then
if value ~= nil then
            return false
table.insert(parts, name .. "=" .. tostring(value))
        end
end
    end
end


    return true
addField("sprite", normalizeSpritePath(entry.sprite))
addField("state", entry.state)
addField("scale", entry.scale)
addField("enableOverrideDir", entry.enableOverrideDir)
addField("overrideDir", entry.overrideDir)
 
if entry.layers and type(entry.layers) == "table" then
local layers = {}
 
for _, layer in ipairs(entry.layers) do
local layerParts = {}
 
for k, v in pairs(layer) do
if type(v) ~= "table" then
layerParts[#layerParts + 1] = k .. "=" .. tostring(v)
end
end
 
table.sort(layerParts)
table.insert(layers, table.concat(layerParts, ","))
end
 
table.sort(layers)
table.insert(parts, "layers=" .. table.concat(layers, "|"))
end
 
table.sort(parts)
return table.concat(parts, ";")
end
 
local function getSpriteStates(entry)
local result = {}
 
if entry.layers and type(entry.layers) == "table" then
for _, layer in ipairs(entry.layers) do
if layer.visible ~= false and layer.state then
table.insert(result, {
state = tostring(layer.state),
sprite = normalizeSpritePath(layer.sprite or entry.sprite)
})
end
end
elseif entry.state and entry.sprite then
table.insert(result, {
state = tostring(entry.state),
sprite = normalizeSpritePath(entry.sprite)
})
end
 
return (#result > 0) and result or nil
end
end


-- Получение пути спрайта
local function getSpritePath(entry)
local function getSpritePath(entry)
    if entry.Sprite and entry.Sprite.sprite then
if entry.sprite then
        return entry.Sprite.sprite
return normalizeSpritePath(entry.sprite)
    elseif entry.Icon and entry.Icon.sprite then
end
        return entry.Icon.sprite
 
    elseif entry.Sprite and entry.Sprite.layers then
if entry.layers and type(entry.layers) == "table" then
        for _, layer in pairs(entry.Sprite.layers) do
for _, layer in ipairs(entry.layers) do
            if layer.sprite then
if layer.sprite then
                return layer.sprite
return normalizeSpritePath(layer.sprite)
            end
end
        end
end
    end
end
    return nil
 
return nil
end
 
local function splitCsv(value)
local result = {}
 
if value == nil then
return nil
end
 
value = mw.text.trim(tostring(value))
if value == "" then
return nil
end
 
for part in mw.text.gsplit(value, ",", true) do
local item = mw.text.trim(part)
if item ~= "" then
table.insert(result, item)
end
end
 
return (#result > 0) and result or nil
end
end


-- Генерация шаблона repeat
local function buildSet(value)
local function generateRepeatTemplate(data)
local list = splitCsv(value)
    local spriteGroups = {}
if not list then
return nil
end


    for _, entry in pairs(data) do
local set = {}
        local found = false
for _, item in ipairs(list) do
        for _, group in pairs(spriteGroups) do
set[item] = true
            if deepEqual(entry.Sprite, group[1].Sprite) and
end
              deepEqual(entry.EntityStorageVisuals, group[1].EntityStorageVisuals) and
              deepEqual(entry.Icon, group[1].Icon) then
                table.insert(group, entry)
                found = true
                break
            end
        end


        if not found then
return set
            table.insert(spriteGroups, {entry})
end
        end
    end


    local result = {}
local function getParents(parentData, id)
    for _, group in pairs(spriteGroups) do
if not parentData or type(parentData) ~= "table" or not id then
        if #group > 1 then
return nil
            local idLinks = {}
end
            for _, entry in pairs(group) do
                table.insert(idLinks, "[[:Файл:" .. entry.id .. ".png]]")
            end
            table.insert(result, mw.getCurrentFrame():preprocess("{{Entity Sprite/Repeat|" .. table.concat(idLinks, " ") .. "|" .. group[1].id .. "}}"))
        end
    end


    return table.concat(result, "\n")
local parents = parentData[id]
if type(parents) ~= "table" then
return nil
end
 
return parents
end
end


-- Обновляем основную функцию
local function hasAnyParent(parents, set)
local function generateTemplate(entry, param, secondaryParam, data)
if not parents or not set then
    local spritePath = getSpritePath(entry)
return false
    if not entry.id or not spritePath then
end
        return nil
    end


    if param == "image" then
for _, parent in ipairs(parents) do
        if secondaryParam then
if set[parent] then
            if tostring(entry.id) == tostring(secondaryParam) then
return true
                return spritePath
end
            end
end
            return nil
        else
            return mw.getCurrentFrame():preprocess("{{Entity Sprite/Image|" .. entry.id .. "|" .. spritePath .. "}}")
        end
    elseif param == "path" then
        if secondaryParam then
            for _, e in pairs(data) do
                if getSpritePath(e) == secondaryParam then
                    return e.id
                end
            end
            return nil
        end
        return mw.getCurrentFrame():preprocess("{{Entity Sprite/Path|" .. entry.id .. "|" .. spritePath .. "}}")
    end


    return nil
return false
end
end


-- Генерация шаблона по умолчанию
local function shouldIncludeEntry(id, whitelistSet, blacklistSet, parentData)
local function generateDefaultTemplate(data, params)
local parents = getParents(parentData, id)
    local id = params.Id
 
    local description = params.Description or ""
if whitelistSet and not hasAnyParent(parents, whitelistSet) then
    local servers = params.Servers or ""
return false
    local source = params.Source or ""
end
    local tags = params.Tags or ""
 
if blacklistSet and hasAnyParent(parents, blacklistSet) then
return false
end


    local spritePath = nil
return true
    local path = params.Path
end


    local entry = nil
local function filterSpriteData(spriteData, parentData, whitelistSet, blacklistSet, project)
    if id and id ~= "" then
local result = {}
        for _, item in pairs(data) do
            if tostring(item.id) == tostring(id) then
                entry = item
                break
            end
        end
    end


    if entry then
for id, entry in pairs(spriteData) do
        spritePath = getSpritePath(entry)
if shouldIncludeEntry(id, whitelistSet, blacklistSet, parentData) then
        if not spritePath then
if project == "" or JsonPaths.has(id, project) then
            return ""
result[id] = entry
        end
end
    end
end
   
end
    if not path or path == "" then
        path = "Resources/Textures/" .. (spritePath or "")
    end


    return mw.getCurrentFrame():preprocess(
return result
        "{{Файл\n" ..
end
        "|Описание = " .. description .. "\n" ..
 
        "|Id      = " .. id .. "\n" ..
local function buildFileLink(id, project)
        "|Сервера  = " .. servers .. "\n" ..
return "[[:Файл:" .. JsonPaths.prefixFile(id) .. ".png]]"
        "|Источник = " .. source .. "\n" ..
end
        "|Путь    = " .. path .. "\n" ..
 
        "|Теги    = " .. tags .. "\n" ..
local function buildSpriteUrl(baseUrl, spritePath)
        "}}\n"
return baseUrl .. spritePath
    )
end
 
local function buildSpritePathLink(baseUrl, spritePath)
local url = buildSpriteUrl(baseUrl, spritePath)
return "[" .. url .. " " .. spritePath .. "]"
end
 
local function buildStateLink(baseUrl, spritePath, state)
local url = buildSpriteUrl(baseUrl, spritePath) .. "/" .. state .. ".png"
return "[" .. url .. " " .. state .. "]"
end
 
local function buildSpriteStateLinks(baseUrl, states)
if not states or #states == 0 then
return ""
end
 
local links = {}
 
for _, item in ipairs(states) do
if item.sprite and item.state then
table.insert(links, buildStateLink(baseUrl, item.sprite, item.state))
end
end
 
return table.concat(links, ", ")
end
 
local function buildRepeatSpriteValue(baseUrl, entry)
local spritePath = getSpritePath(entry)
if not spritePath then
return ""
end
 
local pathLink = buildSpritePathLink(baseUrl, spritePath)
local states = getSpriteStates(entry)
 
if states and #states > 0 and states[1].state and states[1].state ~= "" then
return pathLink .. " (" .. buildStateLink(baseUrl, spritePath, states[1].state) .. ")"
end
 
return pathLink
end
 
local function generateRepeatTemplate(data, project, baseUrl)
local spriteGroups = {}
 
for id, entry in pairs(data) do
local key = buildEntryKey(entry)
 
spriteGroups[key] = spriteGroups[key] or {}
table.insert(spriteGroups[key], { id = id, entry = entry })
end
 
local result = {}
 
for _, group in pairs(spriteGroups) do
if #group > 1 then
local idLinks = {}
 
for _, obj in ipairs(group) do
table.insert(idLinks, buildFileLink(obj.id, project))
end
 
local firstId = group[1].id
local firstEntry = group[1].entry
local spriteValue = buildRepeatSpriteValue(baseUrl, firstEntry)
 
table.insert(result, mw.getCurrentFrame():preprocess(
"{{Entity Sprite/Repeat|файлы=" .. table.concat(idLinks, " ") ..
"|перенаправление=" .. JsonPaths.prefixFile(firstId) ..
"|id=" .. firstId ..
"|спрайт=" .. spriteValue ..
"}}"
))
end
end
 
return table.concat(result, "\n")
end
 
local function generateTemplate(id, entry, baseUrl, project)
local spritePath = getSpritePath(entry)
if not id or not spritePath then
return nil
end
 
local states = getSpriteStates(entry)
local stateStr = buildSpriteStateLinks(baseUrl, states)
 
return mw.getCurrentFrame():preprocess(
"{{Entity Sprite/Image|файл=" .. JsonPaths.prefixFile(id) ..
"|id=" .. id ..
"|путь=" .. buildSpriteUrl(baseUrl, spritePath) ..
"|state=" .. stateStr ..
"}}"
)
end
end


function p.main(frame)
function p.main(frame)
    local param = frame.args[1]
local action = frame.args[1]
    local secondaryParam = frame.args[2]
local json = frame.args.json or "component/Sprite.json"
 
local project = JsonPaths.project()
local baseUrl = JsonPaths.git() .. "/Resources/Textures/"
 
local dataPage = JsonPaths.get(json)
local parentPage = JsonPaths.get("entity parent.json")
 
local spriteDataRaw = mw.loadData(dataPage)
local parentDataRaw = mw.loadData(parentPage)
 
local spriteData = normalizeData(spriteDataRaw)
local parentData = normalizeData(parentDataRaw)
 
if not spriteData or type(spriteData) ~= "table" then
return "Ошибка загрузки JSON: " .. dataPage
end
 
if not parentData or type(parentData) ~= "table" then
return "Ошибка загрузки JSON: " .. parentPage
end
 
local whitelistSet = buildSet(frame.args.whitelistParent)
local blacklistSet = buildSet(frame.args.blacklistParent)
local filteredData = filterSpriteData(spriteData, parentData, whitelistSet, blacklistSet, project)
 
if action == "repeat" then
return generateRepeatTemplate(filteredData, project, baseUrl)
elseif action == "image" then
local result = {}
 
for id, entry in pairs(filteredData) do
local t = generateTemplate(id, entry, baseUrl, project)
if t then
table.insert(result, t)
end
end


    local data = loadData('User:IanComradeBot/prototypes/entity sprite.json')
return table.concat(result, "\n")
    if not data or type(data) ~= 'table' then
end
        return 'Ошибка: Невозможно загрузить данные из JSON.'
    end


    if param == "repeat" then
return nil
        return generateRepeatTemplate(data)
    elseif param == "path" and secondaryParam then
        for _, entry in ipairs(data) do
            local template = generateTemplate(entry, param, secondaryParam, data)
            if template then
                return template
            end
        end
        return nil  
    elseif param == "image" or param == "path" then
        local result = {}
        for _, entry in pairs(data) do
            local template = generateTemplate(entry, param, secondaryParam, data)
            if template then
                table.insert(result, template)
            end
        end
        return table.concat(result, "\n")
    else
        return generateDefaultTemplate(data, frame.args)
    end
end
end


return p
return p