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

мНет описания правки
мНет описания правки
 
(не показано 112 промежуточных версий этого же участника)
Строка 1: Строка 1:
-- Загрузка данных
local spriteData = mw.loadData("Модуль:IanComradeBot/prototypes/entity sprite.json/data")
local p = {}
local p = {}


-- Загрузка данных
-- Функция для получения таблицы данных
local function loadData(filePath)
function p.getData()
    local page = mw.title.new(filePath)
     return spriteData
    local content = page and page:getContent()
     return content and mw.text.jsonDecode(content) or nil
end
end


-- Проверка равенства двух таблиц
-- Функция нечувствительного к регистру поиска поля
local function deepEqual(t1, t2)
local function findFieldInsensitive(tbl, fieldName)
     if t1 == t2 then return true end
     for key, value in pairs(tbl) do
    if type(t1) ~= "table" or type(t2) ~= "table" then return false end
        if type(key) == "string" and mw.ustring.lower(key) == mw.ustring.lower(fieldName) then
 
            return value
    for k, v in pairs(t1) do
         end
         if not deepEqual(v, t2[k]) then return false end
     end
     end
    return nil
end


     for k, v in pairs(t2) do
-- Функция получения пути спрайта: сначала пытаем Icon.sprite, затем Sprite.sprite, затем первый layer.sprite
        if not deepEqual(v, t1[k]) then return false end
local function getSpritePath(entry)
     local iconBlock = findFieldInsensitive(entry, "Icon")
    if type(iconBlock) == "table" and iconBlock.sprite then
        return iconBlock.sprite
     end
     end


     return true
     local spriteBlock = findFieldInsensitive(entry, "Sprite")
end
    if not spriteBlock then return nil end


-- Генерация шаблона repeat
    if type(spriteBlock) == "string" then
local function generateRepeatTemplate(data)
        return spriteBlock
     local spriteGroups = {}
     end


     for _, entry in ipairs(data) do
     if spriteBlock.sprite then
        if entry.Sprite and entry.EntityStorageVisuals then
        return spriteBlock.sprite
            local key = mw.text.jsonEncode({ Sprite = entry.Sprite, EntityStorageVisuals = entry.EntityStorageVisuals })
            spriteGroups[key] = spriteGroups[key] or {}
            table.insert(spriteGroups[key], entry.id)
        end
     end
     end


     local result = {}
     if spriteBlock.layers then
    for _, ids in pairs(spriteGroups) do
        for _, layer in pairs(spriteBlock.layers) do
        if #ids > 1 then
            if layer.sprite then
            local idLinks = {}
                 return layer.sprite
            for _, id in ipairs(ids) do
                 table.insert(idLinks, "[[:Файл:" .. id .. ".png]]")
             end
             end
            local firstId = ids[1]
            table.insert(result, mw.getCurrentFrame():preprocess("{{Entity Sprite/Repeat|" .. table.concat(idLinks, " ") .. "|" .. firstId .. "}}"))
         end
         end
     end
     end


     return table.concat(result, "\n")
     return nil
end
end


-- Генерация текста для элемента JSON
-- Проверка visible и shader
local function generateTemplate(entry, param)
local function isLayerVisibleAndShaded(layer)
     if not entry.id or not entry.Sprite or not entry.Sprite.sprite then
     if layer.visible == false then return false end
         return nil
    if layer.shader and layer.shader == "unshaded" then return false end
    return true
end
 
-- Функция определения, что поле state первое
local function isStateFirstKey(layer)
    for k, _ in pairs(layer) do
         return k == "state"
     end
     end
    return false
end
-- Функция получения списка состояний с учётом переопределяющего sprite в слое
local function getSpriteStates(entry)
    local result = {}


     if param == "image" then
     local function addState(state, sprite)
        return mw.getCurrentFrame():preprocess("{{Entity Sprite/Imege|" .. entry.id .. "|" .. entry.Sprite.sprite .. "}}")
         table.insert(result, { state = state, sprite = sprite })
    elseif param == "license" then
         return mw.getCurrentFrame():preprocess("{{Entity Sprite/License|" .. entry.id .. "|" .. entry.Sprite.sprite .. "}}")
     end
     end


     return nil
     local spritePath = getSpritePath(entry)
end
    local iconBlock = findFieldInsensitive(entry, "Icon")


-- Генерация шаблона по умолчанию
    if iconBlock and iconBlock.state and isLayerVisibleAndShaded(iconBlock) then
local function generateDefaultTemplate(entry, params)
        local s = (type(iconBlock) == "table" and iconBlock.sprite) or spritePath
    local description = params.Description or ""
        addState(iconBlock.state, s)
    local id = params.Id or entry.id
     else
     local servers = params.Servers or ""
        local spriteBlock = findFieldInsensitive(entry, "Sprite")
    local source = params.Source or ""
        if spriteBlock and spriteBlock.layers then
    local path = params.Path
            for _, layer in ipairs(spriteBlock.layers) do
    local tags = params.Tags or ""
                if layer.state and isLayerVisibleAndShaded(layer) then
    local licensing = params.Licensing or "CC-BY-SA-3.0"
                    local s = layer.sprite or spritePath
                    addState(layer.state, s)
                    break
                end
            end
        elseif spriteBlock and spriteBlock.state and isLayerVisibleAndShaded(spriteBlock) then
            addState(spriteBlock.state, spritePath)
        end
    end


     if not entry.id or not entry.Sprite or not entry.Sprite.sprite then
     local spriteBlock = findFieldInsensitive(entry, "Sprite")
         return nil
    if spriteBlock and spriteBlock.layers then
        for _, layer in ipairs(spriteBlock.layers) do
            local alreadyAdded = false
            for _, r in ipairs(result) do
                if r.state == layer.state then
                    alreadyAdded = true
                    break
                end
            end
            if not alreadyAdded and layer.state and isStateFirstKey(layer) and isLayerVisibleAndShaded(layer) then
                local s = layer.sprite or spritePath
                addState(layer.state, s)
            end
         end
     end
     end


     if not path or path == "" then
     if #result == 0 and spritePath then
         path = "Resources/Textures/" .. entry.Sprite.sprite
         addState("icon", spritePath)
     end
     end


    -- Формирование шаблона
     return (#result > 0) and result or nil
     return mw.getCurrentFrame():preprocess(
        "\n== Краткое описание ==\n" ..
        "{{Файл\n" ..
        "|Описание = " .. description .. "\n" ..
        "|Id      = " .. id .. "\n" ..
        "|Сервера  = " .. servers .. "\n" ..
        "|Источник = " .. source .. "\n" ..
        "|Путь    = " .. path .. "\n" ..
        "|Теги    = " .. tags .. "\n" ..
        "}}\n\n" ..
        "== Лицензирование ==\n" ..
        "{{" .. licensing .. "}}"
    )
end
end


-- Основная функция модуля
-- Функция генерации шаблона по записи (mode: image, path, state)
function p.main(frame)
function p.main(frame)
     local param = frame.args[1]
     local mode = frame.args[1]
    local id = frame.args[2]
    if not mode or not id then
        return "Ошибка: отсутствует режим или ID"
    end


     if not param then
     for _, entry in ipairs(spriteData) do
        local data = loadData('User:IanComradeBot/prototypes/entity sprite.json')
        if entry.id == id then
        if not data or type(data) ~= 'table' then
            if mode == "image" then
            return 'Ошибка: Невозможно загрузить данные из JSON.'
                local sprite = getSpritePath(entry)
                return sprite or "Ошибка: спрайт не найден"
            elseif mode == "path" then
                if getSpritePath(entry) == id then
                    return entry.id
                end
            elseif mode == "state" then
                local states = getSpriteStates(entry)
                if not states then
                    return ""
                end
                local baseUrl = "https://github.com/space-syndicate/space-station-14/blob/master/Resources/Textures/"
                local links = {}
                for _, item in ipairs(states) do
                    local spritePath = item.sprite
                    local stateName = item.state
                    if spritePath then
                        local url = baseUrl .. spritePath .. "/" .. stateName .. ".png"
                        table.insert(links, "[" .. url .. " " .. stateName .. "]")
                    else
                        table.insert(links, stateName .. " Error: sprite not found")
                    end
                end
                return "(state: " .. table.concat(links, ", ") .. ")"
            end
         end
         end
        local entry = data[1]
        if not entry then
            return 'Ошибка: Не найден элемент с таким ID.'
        end
       
        -- Генерация шаблона по умолчанию
        return generateDefaultTemplate(entry, frame.args)
     end
     end


    -- Логика для других параметров, как "image", "license", "repeat"
     if mode == "path" then
     if param == "repeat" then
         return "Ошибка: путь не найден"
         local data = loadData('User:IanComradeBot/prototypes/entity sprite.json')
     elseif mode == "image" then
        if not data or type(data) ~= 'table' then
        return "Ошибка: ID не найден"
            return 'Ошибка: Невозможно загрузить данные из JSON.'
    elseif mode == "state" then
        end
         return "Ошибка: ID не найден"
        return generateRepeatTemplate(data)
     else
        local data = loadData('User:IanComradeBot/prototypes/entity sprite.json')
        if not data or type(data) ~= 'table' then
            return 'Ошибка: Невозможно загрузить данные из JSON.'
        end
 
        local result = {}
        for _, entry in ipairs(data) do
            local template = generateTemplate(entry, param)
            if template then
                table.insert(result, template)
            end
        end
         return table.concat(result)
     end
     end
    return "Ошибка: неизвестный режим"
end
end


return p
return p