Модуль: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 -- Если это ма...»
 
Нет описания правки
 
(не показано 38 промежуточных версий этого же участника)
Строка 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 buildEntryKey(entry)
local function deepEqual(t1, t2)
local parts = {}
    if t1 == t2 then return true end
 
    if type(t1) ~= "table" or type(t2) ~= "table" then return false end
if entry.sprite then
table.insert(parts, "sprite=" .. normalizeSpritePath(entry.sprite))
end
 
if entry.layers and type(entry.layers) == "table" then
local layers = {}


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


    if isArray(t1) and isArray(t2) then
for k, v in pairs(layer) do
        if #t1 ~= #t2 then return false end
layerParts[#layerParts+1] = k .. "=" .. tostring(v)
        local matched = {}
end
        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


    -- Если это таблицы, проверяем их содержимое
table.sort(layerParts)
    for k, v in pairs(t1) do
table.insert(layers, table.concat(layerParts, ","))
        if not deepEqual(v, t2[k]) then
end
            return false
        end
    end


    for k, v in pairs(t2) do
table.sort(layers)  
        if not deepEqual(v, t1[k]) then
table.insert(parts, "layers=" .. table.concat(layers, "|"))
            return false
end
        end
    end


    return true
return table.concat(parts, ";")
end
end


-- Получение пути спрайта
local function getSpritePath(entry)
local function getSpritePath(entry)
    if entry.Sprite and entry.Sprite.sprite then
return normalizeSpritePath(entry.sprite)
        return entry.Sprite.sprite
end
    elseif entry.Icon and entry.Icon.sprite then
 
        return entry.Icon.sprite
local function getSpriteStates(entry)
    elseif entry.Sprite and entry.Sprite.layers then
local result = {}
        for _, layer in pairs(entry.Sprite.layers) do
 
            if layer.sprite then
if entry.layers and type(entry.layers) == "table" then
                return layer.sprite
for _, layer in ipairs(entry.layers) do
            end
if layer.visible ~= false then
        end
table.insert(result, {
    end
state = tostring(layer.state or entry.state or ""),
    return nil
sprite = normalizeSpritePath(layer.sprite or entry.sprite)
})
end
end
elseif entry.state and entry.sprite then
table.insert(result, {
state = tostring(entry.state or ""),
sprite = normalizeSpritePath(entry.sprite)
})
end
 
return (#result > 0) and result or nil
end
 
local function getPrefix(id, project)
if project ~= "" and JsonPaths.has(id, project) then
return project .. ":"
end
return ""
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
 
local function buildSet(value)
local list = splitCsv(value)
if not list then
return nil
end
 
local set = {}
for _, item in ipairs(list) do
set[item] = true
end
 
return set
end
 
local function getParents(entry)
if not entry then
return nil
end
 
if type(entry.parents) == "table" then
return entry.parents
end
 
if type(entry.parents) == "string" then
return splitCsv(entry.parents)
end
 
return nil
end
end


-- Генерация шаблона repeat
local function hasAnyParent(parents, set)
local function generateRepeatTemplate(data)
if not parents or not set then
    local spriteGroups = {}
return false
end
 
for _, parent in ipairs(parents) do
if set[parent] then
return true
end
end
 
return false
end


    for _, entry in pairs(data) do
local function shouldIncludeEntry(entry, whitelistSet, blacklistSet)
        local found = false
local parents = getParents(entry)
        for _, group in pairs(spriteGroups) do
            if deepEqual(entry.Sprite, group[1].Sprite) and
              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
if whitelistSet then
            table.insert(spriteGroups, {entry})
if not hasAnyParent(parents, whitelistSet) then
        end
return false
    end
end
end


    local result = {}
if blacklistSet and hasAnyParent(parents, blacklistSet) then
    for _, group in pairs(spriteGroups) do
return false
        if #group > 1 then
end
            local idLinks = {}
            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")
return true
end
end


-- Обновляем основную функцию
local function filterSpriteData(spriteData, prototypeData, whitelistSet, blacklistSet)
local function generateTemplate(entry, param, secondaryParam, data)
local result = {}
    local spritePath = getSpritePath(entry)
 
    if not entry.id or not spritePath then
for id, entry in pairs(spriteData) do
        return nil
local protoEntry = prototypeData and prototypeData[id] or entry
    end


    if param == "image" then
if shouldIncludeEntry(protoEntry, whitelistSet, blacklistSet) then
        if secondaryParam then
result[id] = entry
            if tostring(entry.id) == tostring(secondaryParam) then
end
                return spritePath
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 result
end
end


-- Генерация шаблона по умолчанию
local function generateRepeatTemplate(data, project)
local function generateDefaultTemplate(data, params)
local spriteGroups = {}
    local id = params.Id
 
    local description = params.Description or ""
for id, entry in pairs(data) do
    local servers = params.Servers or ""
local key = buildEntryKey(entry)
    local source = params.Source or ""
    local tags = params.Tags or ""


    local spritePath = nil
spriteGroups[key] = spriteGroups[key] or {}
    local path = params.Path
table.insert(spriteGroups[key], { id = id, entry = entry })
end


    local entry = nil
local result = {}
    if id and id ~= "" then
        for _, item in pairs(data) do
            if tostring(item.id) == tostring(id) then
                entry = item
                break
            end
        end
    end


    if entry then
for _, group in pairs(spriteGroups) do
        spritePath = getSpritePath(entry)
if #group > 1 then
        if not spritePath then
local idLinks = {}
            return ""
        end
for _, obj in ipairs(group) do
    end
local id = obj.id
   
local prefix = getPrefix(id, project)
    if not path or path == "" then
        path = "Resources/Textures/" .. (spritePath or "")
table.insert(idLinks, "[[:Файл:" .. prefix .. id .. ".png]]")
    end
end
local firstId = group[1].id
local prefix = getPrefix(firstId, project)
table.insert(result, mw.getCurrentFrame():preprocess(
"{{Entity Sprite/Repeat|спрайты=" .. table.concat(idLinks, " ") ..
"|перенаправление=" .. prefix .. firstId ..
"|id=" .. firstId ..
"}}"
))
end
end


    return mw.getCurrentFrame():preprocess(
return table.concat(result, "\n")
        "{{Файл\n" ..
end
        "|Описание = " .. description .. "\n" ..
 
        "|Id      = " .. id .. "\n" ..
local function generateTemplate(id, entry, baseUrl, project)
        "|Сервера  = " .. servers .. "\n" ..
local spritePath = getSpritePath(entry)
        "|Источник = " .. source .. "\n" ..
if not id or not spritePath then
        "|Путь    = " .. path .. "\n" ..
return nil
        "|Теги    = " .. tags .. "\n" ..
end
        "}}\n"
 
    )
local prefix = getPrefix(id, project)
 
local states = getSpriteStates(entry)
local stateStr = ""
 
if states then
local links = {}
for _, item in ipairs(states) do
if item.sprite and item.state then
local url = baseUrl .. item.sprite .. "/" .. item.state .. ".png"
table.insert(links, "[" .. url .. " " .. item.state .. "]")
end
end
stateStr = table.concat(links, ", ")
end
 
return mw.getCurrentFrame():preprocess(
"{{Entity Sprite/Image|файл=" .. prefix .. id ..
"|id=" .. id ..
"|путь=" .. 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 "sprite_entity.json"
 
local project = JsonPaths.project()
local baseUrl = JsonPaths.git() .. "/Resources/Textures/"
 
local dataPage = JsonPaths.get(json)
local prototypesPage = JsonPaths.get("entity prototypes.json")
 
local spriteData = mw.loadData(dataPage)
local prototypeData = mw.loadData(prototypesPage)
 
if not spriteData or type(spriteData) ~= "table" then
return "Ошибка загрузки JSON: " .. dataPage
end
 
if not prototypeData or type(prototypeData) ~= "table" then
return "Ошибка загрузки JSON: " .. prototypesPage
end
 
local whitelistSet = buildSet(frame.args.whitelistParent)
local blacklistSet = buildSet(frame.args.blacklistParent)
 
local filteredData = filterSpriteData(spriteData, prototypeData, whitelistSet, blacklistSet)
 
if action == "repeat" then
return generateRepeatTemplate(filteredData, project)
 
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