Модуль:Entity Sprite/all: различия между версиями
Материал из Space Station 14 Вики
Pok (обсуждение | вклад) мНет описания правки |
Pok (обсуждение | вклад) Нет описания правки |
||
| (не показаны 23 промежуточные версии этого же участника) | |||
| Строка 1: | Строка 1: | ||
local p = {} | local p = {} | ||
local JsonPaths = require('Module:JsonPaths') | |||
local function | local function normalizeSpritePath(path) | ||
if path == nil then | |||
return nil | |||
end | |||
path = mw.text.trim(tostring(path)) | |||
path = path:gsub("^/Textures/?", "") | |||
return path | |||
end | |||
local function buildEntryKey(entry) | |||
local parts = {} | |||
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 layerParts = {} | |||
for k, v in pairs(layer) do | |||
end | layerParts[#layerParts+1] = k .. "=" .. tostring(v) | ||
end | |||
table.sort(layerParts) | |||
table.insert(layers, table.concat(layerParts, ",")) | |||
end | |||
table.sort(layers) | |||
table.insert(parts, "layers=" .. table.concat(layers, "|")) | |||
end | |||
return table.concat(parts, ";") | |||
end | end | ||
local function getSpritePath(entry) | local function getSpritePath(entry) | ||
return normalizeSpritePath(entry.sprite) | |||
end | end | ||
local function getSpriteStates(entry) | 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 then | |||
table.insert(result, { | |||
state = tostring(layer.state or entry.state or ""), | |||
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 | end | ||
local function | 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 | ||
local function | local function hasAnyParent(parents, set) | ||
if not parents or not set then | |||
return false | |||
end | |||
for _, parent in ipairs(parents) do | |||
if set[parent] then | |||
return true | |||
end | |||
end | |||
return false | |||
end | |||
local function shouldIncludeEntry(entry, whitelistSet, blacklistSet) | |||
local parents = getParents(entry) | |||
if whitelistSet then | |||
if not hasAnyParent(parents, whitelistSet) then | |||
return false | |||
end | |||
end | |||
if blacklistSet and hasAnyParent(parents, blacklistSet) then | |||
return false | |||
end | |||
return true | |||
end | |||
local function filterSpriteData(spriteData, prototypeData, whitelistSet, blacklistSet) | |||
local result = {} | |||
for id, entry in pairs(spriteData) do | |||
local protoEntry = prototypeData and prototypeData[id] or entry | |||
if shouldIncludeEntry(protoEntry, whitelistSet, blacklistSet) then | |||
result[id] = entry | |||
end | |||
end | |||
return result | |||
end | |||
local function generateRepeatTemplate(data, project) | |||
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 | |||
local id = obj.id | |||
local prefix = getPrefix(id, project) | |||
table.insert(idLinks, "[[:Файл:" .. prefix .. id .. ".png]]") | |||
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 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 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 action = frame.args[1] | |||
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 | |||
return table.concat(result, "\n") | |||
end | |||
return nil | |||
end | end | ||
return p | return p | ||
Текущая версия от 03:10, 22 марта 2026
Для документации этого модуля может быть создана страница Модуль:Entity Sprite/all/doc
local p = {}
local JsonPaths = require('Module:JsonPaths')
local function normalizeSpritePath(path)
if path == nil then
return nil
end
path = mw.text.trim(tostring(path))
path = path:gsub("^/Textures/?", "")
return path
end
local function buildEntryKey(entry)
local parts = {}
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 layerParts = {}
for k, v in pairs(layer) do
layerParts[#layerParts+1] = k .. "=" .. tostring(v)
end
table.sort(layerParts)
table.insert(layers, table.concat(layerParts, ","))
end
table.sort(layers)
table.insert(parts, "layers=" .. table.concat(layers, "|"))
end
return table.concat(parts, ";")
end
local function getSpritePath(entry)
return normalizeSpritePath(entry.sprite)
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 then
table.insert(result, {
state = tostring(layer.state or entry.state or ""),
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
local function hasAnyParent(parents, set)
if not parents or not set then
return false
end
for _, parent in ipairs(parents) do
if set[parent] then
return true
end
end
return false
end
local function shouldIncludeEntry(entry, whitelistSet, blacklistSet)
local parents = getParents(entry)
if whitelistSet then
if not hasAnyParent(parents, whitelistSet) then
return false
end
end
if blacklistSet and hasAnyParent(parents, blacklistSet) then
return false
end
return true
end
local function filterSpriteData(spriteData, prototypeData, whitelistSet, blacklistSet)
local result = {}
for id, entry in pairs(spriteData) do
local protoEntry = prototypeData and prototypeData[id] or entry
if shouldIncludeEntry(protoEntry, whitelistSet, blacklistSet) then
result[id] = entry
end
end
return result
end
local function generateRepeatTemplate(data, project)
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
local id = obj.id
local prefix = getPrefix(id, project)
table.insert(idLinks, "[[:Файл:" .. prefix .. id .. ".png]]")
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 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 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
function p.main(frame)
local action = frame.args[1]
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
return table.concat(result, "\n")
end
return nil
end
return p