Модуль:Entity Sprite/all: различия между версиями
Материал из Space Station 14 Вики
Pok (обсуждение | вклад) Нет описания правки |
Pok (обсуждение | вклад) Нет описания правки |
||
| Строка 11: | Строка 11: | ||
return path | return path | ||
end | |||
local function getSpritePath(entry) | |||
return entry and normalizeSpritePath(entry.sprite) or nil | |||
end | |||
local function getSpriteStates(entry) | |||
local result = {} | |||
if entry and entry.layers and type(entry.layers) == "table" then | |||
for _, layer in ipairs(entry.layers) do | |||
if layer.visible ~= false and layer.state then | |||
result[#result + 1] = { | |||
state = tostring(layer.state), | |||
sprite = normalizeSpritePath(layer.sprite or entry.sprite) | |||
} | |||
end | |||
end | |||
elseif entry and entry.state and entry.sprite then | |||
result[#result + 1] = { | |||
state = tostring(entry.state), | |||
sprite = normalizeSpritePath(entry.sprite) | |||
} | |||
end | |||
return (#result > 0) and result or nil | |||
end | |||
local function getPrimaryState(entry) | |||
local states = getSpriteStates(entry) | |||
if states and states[1] and states[1].state and states[1].state ~= "" then | |||
return states[1].state | |||
end | |||
if entry and entry.state then | |||
return tostring(entry.state) | |||
end | |||
return nil | |||
end | |||
local function buildSpriteLink(baseUrl, spritePath) | |||
return "[" .. baseUrl .. spritePath .. " " .. spritePath .. "]" | |||
end | |||
local function buildStateLink(baseUrl, spritePath, stateName) | |||
return "[" .. baseUrl .. spritePath .. "/" .. stateName .. ".png " .. stateName .. "]" | |||
end | |||
local function buildStateLinks(entry, baseUrl) | |||
local spritePath = getSpritePath(entry) | |||
local states = getSpriteStates(entry) | |||
if not spritePath or not states then | |||
return nil | |||
end | |||
local links = {} | |||
for _, item in ipairs(states) do | |||
if item.sprite and item.state then | |||
links[#links + 1] = buildStateLink(baseUrl, item.sprite, item.state) | |||
end | |||
end | |||
return (#links > 0) and links or nil | |||
end | |||
local function renderTemplate(template) | |||
return mw.getCurrentFrame():preprocess(template) | |||
end | end | ||
| Строка 18: | Строка 89: | ||
local function addField(name, value) | local function addField(name, value) | ||
if value ~= nil then | if value ~= nil then | ||
parts[#parts + 1] = name .. "=" .. tostring(value) | |||
end | end | ||
end | end | ||
addField("sprite", | addField("sprite", getSpritePath(entry)) | ||
addField("state", entry.state) | addField("state", entry.state) | ||
addField("scale", entry.scale) | addField("scale", entry.scale) | ||
| Строка 41: | Строка 112: | ||
table.sort(layerParts) | table.sort(layerParts) | ||
layers[#layers + 1] = table.concat(layerParts, ",") | |||
end | end | ||
table.sort(layers) | table.sort(layers) | ||
parts[#parts + 1] = "layers=" .. table.concat(layers, "|") | |||
end | end | ||
table.sort(parts) | table.sort(parts) | ||
return table.concat(parts, ";") | return table.concat(parts, ";") | ||
end | end | ||
| Строка 100: | Строка 138: | ||
local item = mw.text.trim(part) | local item = mw.text.trim(part) | ||
if item ~= "" then | if item ~= "" then | ||
result[#result + 1] = item | |||
end | end | ||
end | end | ||
| Строка 154: | Строка 192: | ||
local parents = getParents(entry) | local parents = getParents(entry) | ||
if whitelistSet | if whitelistSet and not hasAnyParent(parents, whitelistSet) then | ||
return false | |||
end | end | ||
| Строка 179: | Строка 215: | ||
return result | return result | ||
end | end | ||
| Строка 257: | Строка 224: | ||
spriteGroups[key] = spriteGroups[key] or {} | spriteGroups[key] = spriteGroups[key] or {} | ||
spriteGroups[key][#spriteGroups[key] + 1] = { id = id, entry = entry } | |||
end | end | ||
| Строка 268: | Строка 235: | ||
for _, obj in ipairs(group) do | for _, obj in ipairs(group) do | ||
local id = obj.id | local id = obj.id | ||
local prefix = | local prefix = (project ~= "" and JsonPaths.has(id, project)) and (project .. ":") or "" | ||
idLinks[#idLinks + 1] = "[[:Файл:" .. prefix .. id .. ".png]]" | |||
end | end | ||
local firstId = group[1].id | local firstId = group[1].id | ||
local firstEntry = group[1].entry | local firstEntry = group[1].entry | ||
local prefix = | local prefix = (project ~= "" and JsonPaths.has(firstId, project)) and (project .. ":") or "" | ||
local | |||
local spritePath = getSpritePath(firstEntry) | |||
local spriteValue = "" | |||
if spritePath then | |||
spriteValue = buildSpriteLink(baseUrl, spritePath) | |||
local stateName = getPrimaryState(firstEntry) | |||
"{{Entity Sprite/Repeat| | if stateName and stateName ~= "" then | ||
spriteValue = spriteValue .. " (" .. buildStateLink(baseUrl, spritePath, stateName) .. ")" | |||
end | |||
end | |||
result[#result + 1] = renderTemplate( | |||
"{{Entity Sprite/Repeat|файлы=" .. table.concat(idLinks, " ") .. | |||
"|перенаправление=" .. prefix .. firstId .. | "|перенаправление=" .. prefix .. firstId .. | ||
"|id=" .. firstId .. | "|id=" .. firstId .. | ||
"|спрайт=" .. spriteValue .. | "|спрайт=" .. spriteValue .. | ||
"}}" | "}}" | ||
) | |||
end | end | ||
end | end | ||
| Строка 297: | Строка 274: | ||
end | end | ||
local prefix = | local prefix = (project ~= "" and JsonPaths.has(id, project)) and (project .. ":") or "" | ||
local | local stateLinks = buildStateLinks(entry, baseUrl) | ||
local stateStr = "" | local stateStr = stateLinks and table.concat(stateLinks, ", ") or "" | ||
return renderTemplate( | |||
return | |||
"{{Entity Sprite/Image|файл=" .. prefix .. id .. | "{{Entity Sprite/Image|файл=" .. prefix .. id .. | ||
"|id=" .. id .. | "|id=" .. id .. | ||
| Строка 350: | Строка 316: | ||
if action == "repeat" then | if action == "repeat" then | ||
return generateRepeatTemplate(filteredData, project, baseUrl) | return generateRepeatTemplate(filteredData, project, baseUrl) | ||
elseif action == "image" then | elseif action == "image" then | ||
local result = {} | local result = {} | ||
| Строка 357: | Строка 322: | ||
local t = generateTemplate(id, entry, baseUrl, project) | local t = generateTemplate(id, entry, baseUrl, project) | ||
if t then | if t then | ||
result[#result + 1] = t | |||
end | end | ||
end | end | ||
Версия от 21:05, 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 getSpritePath(entry)
return entry and normalizeSpritePath(entry.sprite) or nil
end
local function getSpriteStates(entry)
local result = {}
if entry and entry.layers and type(entry.layers) == "table" then
for _, layer in ipairs(entry.layers) do
if layer.visible ~= false and layer.state then
result[#result + 1] = {
state = tostring(layer.state),
sprite = normalizeSpritePath(layer.sprite or entry.sprite)
}
end
end
elseif entry and entry.state and entry.sprite then
result[#result + 1] = {
state = tostring(entry.state),
sprite = normalizeSpritePath(entry.sprite)
}
end
return (#result > 0) and result or nil
end
local function getPrimaryState(entry)
local states = getSpriteStates(entry)
if states and states[1] and states[1].state and states[1].state ~= "" then
return states[1].state
end
if entry and entry.state then
return tostring(entry.state)
end
return nil
end
local function buildSpriteLink(baseUrl, spritePath)
return "[" .. baseUrl .. spritePath .. " " .. spritePath .. "]"
end
local function buildStateLink(baseUrl, spritePath, stateName)
return "[" .. baseUrl .. spritePath .. "/" .. stateName .. ".png " .. stateName .. "]"
end
local function buildStateLinks(entry, baseUrl)
local spritePath = getSpritePath(entry)
local states = getSpriteStates(entry)
if not spritePath or not states then
return nil
end
local links = {}
for _, item in ipairs(states) do
if item.sprite and item.state then
links[#links + 1] = buildStateLink(baseUrl, item.sprite, item.state)
end
end
return (#links > 0) and links or nil
end
local function renderTemplate(template)
return mw.getCurrentFrame():preprocess(template)
end
local function buildEntryKey(entry)
local parts = {}
local function addField(name, value)
if value ~= nil then
parts[#parts + 1] = name .. "=" .. tostring(value)
end
end
addField("sprite", getSpritePath(entry))
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)
layers[#layers + 1] = table.concat(layerParts, ",")
end
table.sort(layers)
parts[#parts + 1] = "layers=" .. table.concat(layers, "|")
end
table.sort(parts)
return table.concat(parts, ";")
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
result[#result + 1] = 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 and not hasAnyParent(parents, whitelistSet) then
return false
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, baseUrl)
local spriteGroups = {}
for id, entry in pairs(data) do
local key = buildEntryKey(entry)
spriteGroups[key] = spriteGroups[key] or {}
spriteGroups[key][#spriteGroups[key] + 1] = { 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 = (project ~= "" and JsonPaths.has(id, project)) and (project .. ":") or ""
idLinks[#idLinks + 1] = "[[:Файл:" .. prefix .. id .. ".png]]"
end
local firstId = group[1].id
local firstEntry = group[1].entry
local prefix = (project ~= "" and JsonPaths.has(firstId, project)) and (project .. ":") or ""
local spritePath = getSpritePath(firstEntry)
local spriteValue = ""
if spritePath then
spriteValue = buildSpriteLink(baseUrl, spritePath)
local stateName = getPrimaryState(firstEntry)
if stateName and stateName ~= "" then
spriteValue = spriteValue .. " (" .. buildStateLink(baseUrl, spritePath, stateName) .. ")"
end
end
result[#result + 1] = renderTemplate(
"{{Entity Sprite/Repeat|файлы=" .. table.concat(idLinks, " ") ..
"|перенаправление=" .. prefix .. 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 prefix = (project ~= "" and JsonPaths.has(id, project)) and (project .. ":") or ""
local stateLinks = buildStateLinks(entry, baseUrl)
local stateStr = stateLinks and table.concat(stateLinks, ", ") or ""
return renderTemplate(
"{{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, baseUrl)
elseif action == "image" then
local result = {}
for id, entry in pairs(filteredData) do
local t = generateTemplate(id, entry, baseUrl, project)
if t then
result[#result + 1] = t
end
end
return table.concat(result, "\n")
end
return nil
end
return p