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

Материал из Space Station 14 Вики
мНет описания правки
Нет описания правки
 
(не показано 45 промежуточных версий этого же участника)
Строка 1: Строка 1:
local dataModule = mw.loadData("Модуль:Entity Sprite/data")
-- Загрузка данных
if type(dataModule) ~= "table" then
local JsonPaths = require('Module:JsonPaths')
    return "Ошибка: Невозможно загрузить данные."
local spriteData = mw.loadData(JsonPaths.get("prototype/sprite.json"))
end


local p = {}
local p = {}


p.data = dataModule.data
local function normalizeSpritePath(path)
if path == nil then
return nil
end


-- Проверка равенства двух таблиц
path = mw.text.trim(tostring(path))
local function deepEqual(t1, t2)
path = path:gsub("^/Textures/?", "")
    if t1 == t2 then return true end
    if type(t1) ~= "table" or type(t2) ~= "table" then return false end


    -- Если это массивы, проверяем их содержимое без учета порядка
return path
    local function isArray(t)
end
        local i = 0
        for _ in pairs(t) do
            i = i + 1
            if t[i] == nil then return false end
        end
        return true
    end


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


    -- Если это таблицы, проверяем их содержимое
state = mw.text.trim(tostring(state))
    for k, v in pairs(t1) do
if state == "" then
        if t2[k] == nil or not deepEqual(v, t2[k]) then
return nil
            return false
end
        end
    end


    for k, v in pairs(t2) do
return state
        if t1[k] == nil then
end
            return false
 
        end
-- Функция получения таблицы данных
    end
local function getIdTable()
if type(spriteData) == "table" and type(spriteData.id) == "table" then
return spriteData.id
end
return nil
end


    return true
-- Функция для получения таблицы данных
function p.getData()
return getIdTable() or {}
end
end


-- Получение пути спрайта  
-- Функция получения пути спрайта:
-- 1) сначала entry.sprite
-- 2) потом первый layers[*].sprite
local function getSpritePath(entry)
local function getSpritePath(entry)
    if entry.Sprite and entry.Sprite.sprite then
if not entry then
        return entry.Sprite.sprite
return nil
    elseif entry.Icon and entry.Icon.sprite then
end
        return entry.Icon.sprite
 
    elseif entry.Sprite and entry.Sprite.layers then
if entry.sprite then
        for _, layer in ipairs(entry.Sprite.layers) do
return normalizeSpritePath(entry.sprite)
            if layer.sprite then
end
                return layer.sprite
 
            end
if type(entry.layers) == "table" then
        end
for _, layer in ipairs(entry.layers) do
    end
if layer and layer.sprite then
    return nil
return normalizeSpritePath(layer.sprite)
end
end
end
 
return nil
end
 
-- Проверка visible
local function isLayerVisible(layer)
if not layer then
return false
end
return layer.visible ~= false
end
end


-- Генерация шаблона repeat с оптимизированным вызовом preprocess (один раз в конце)
-- Функция получения списка состояний с учётом переопределяющего sprite в слое
local function generateRepeatTemplate(data)
local function getSpriteStates(entry)
    local spriteGroups = {}
local result = {}
local spritePath = getSpritePath(entry)
 
if entry and type(entry.layers) == "table" then
for _, layer in ipairs(entry.layers) do
if isLayerVisible(layer) and layer.state then
table.insert(result, {
state = tostring(layer.state),
sprite = normalizeSpritePath(layer.sprite or spritePath)
})
end
end
elseif entry and entry.state and spritePath then
table.insert(result, {
state = tostring(entry.state),
sprite = spritePath
})
end


    for _, entry in ipairs(data) do
if #result == 0 and spritePath then
        local found = false
table.insert(result, {
        for key, group in pairs(spriteGroups) do
state = "icon",
            if deepEqual(entry.Sprite, group[1].Sprite) and
sprite = spritePath
              deepEqual(entry.EntityStorageVisuals, group[1].EntityStorageVisuals) and
})
              deepEqual(entry.Icon, group[1].Icon) then
end
                table.insert(group, entry)
                found = true
                break
            end
        end


        if not found then
return (#result > 0) and result or nil
            spriteGroups[entry.id] = {entry}
end
        end
    end


    local result = {}
local function findByPathAndState(data, targetPath, targetState)
    for _, group in pairs(spriteGroups) do
for entityId, entry in pairs(data) do
        if #group > 1 then
if getSpritePath(entry) == targetPath then
            local idLinks = {}
local states = getSpriteStates(entry)
            for _, entry in ipairs(group) do
if states then
                table.insert(idLinks, "[[:Файл:" .. entry.id .. ".png]]")
for _, item in ipairs(states) do
            end
if normalizeState(item.state) == targetState then
            local firstId = group[1].id
return entityId
            table.insert(result, "{{Entity Sprite/Repeat|" .. table.concat(idLinks, " ") .. "|" .. firstId .. "}}")
end
        end
end
    end
end
end
end


    return mw.getCurrentFrame():preprocess(table.concat(result, "\n"))
return nil
end
end


-- Создаём индекс для путей
local function findByPath(data, targetPath)
local function createSpritePathIndex(data)
for entityId, entry in pairs(data) do
    local index = {}
if getSpritePath(entry) == targetPath then
    for _, entry in ipairs(data) do
return entityId
        local spritePath = getSpritePath(entry)
end
        if spritePath then
end
            index[spritePath] = entry.id
 
        end
return nil
    end
    return index
end
end


local function generateTemplate(entry, param, secondaryParam, data, spritePathIndex)
-- Функция генерации шаблона по записи (mode: image, path, state)
    local spritePath = getSpritePath(entry)
function p.main(frame)
    if not entry.id or not spritePath then
local mode = frame.args[1]
        return nil
local id = frame.args[2]
    end
local stateArg = frame.args[3]
 
if not mode or not id then
return "Ошибка: отсутствует режим или ID"
end
 
local data = getIdTable()
if not data then
return "Ошибка: неверный формат JSON"
end


    if param == "image" then
if mode == "image" or mode == "state" then
        if secondaryParam then
local entry = data[id]
            if tostring(entry.id) == tostring(secondaryParam) then
if not entry then
                return spritePath
return "Ошибка: ID не найден"
            end
end
            return nil
        else
            return mw.getCurrentFrame():preprocess("{{Entity Sprite/Image|" .. entry.id .. "|" .. spritePath .. "}}")
        end
    elseif param == "path" then
        if secondaryParam then
            local id = spritePathIndex[secondaryParam]
            if id then
                return id
            end
            return nil
        else
            return mw.getCurrentFrame():preprocess("{{Entity Sprite/Path|" .. entry.id .. "|" .. spritePath .. "}}")
        end
    end


    return nil
if mode == "image" then
end
local sprite = getSpritePath(entry)
return sprite or "Ошибка: спрайт не найден"
elseif mode == "state" then
local states = getSpriteStates(entry)
if not states then
return ""
end
 
local baseUrl = JsonPaths.git() .. "/Resources/Textures/"
local links = {}


-- Генерация шаблона по умолчанию
for _, item in ipairs(states) do
local function generateDefaultTemplate(data, params)
local spritePath = item.sprite
    local id = params.Id
local stateName = item.state
    local description = params.Description or ""
    local servers = params.Servers or ""
    local source = params.Source or ""
    local tags = params.Tags or ""


    local spritePath = nil
if spritePath then
    local path = params.Path
local url = baseUrl .. normalizeSpritePath(spritePath) .. "/" .. stateName .. ".png"
table.insert(links, "[" .. url .. " " .. stateName .. "]")
else
table.insert(links, stateName .. " Error: sprite not found")
end
end


    -- Поиск записи с указанным ID
return "(state: " .. table.concat(links, ", ") .. ")"
    local entry = nil
end
    if id and id ~= "" then
end
        for _, item in ipairs(data) do
            if tostring(item.id) == tostring(id) then
                entry = item
                break
            end
        end
    end


    -- Если запись не найдена, ничего не выводим
if mode == "path" then
    if entry then
local targetPath = normalizeSpritePath(id)
        spritePath = getSpritePath(entry)
local targetState = normalizeState(stateArg)
        if not spritePath then
            return ""
        end
    end
   
    -- Если Path не указан, подставляем путь из User:IanComradeBot/prototypes/entity sprite.json
    if not path or path == "" then
        path = "Resources/Textures/" .. (spritePath or "")
    end


    -- Формирование шаблона
if targetState then
    return mw.getCurrentFrame():preprocess(
local byState = findByPathAndState(data, targetPath, targetState)
        "{{Файл\n" ..
if byState then
        "|Описание = " .. description .. "\n" ..
return byState
        "|Id      = " .. id .. "\n" ..
end
        "|Сервера  = " .. servers .. "\n" ..
end
        "|Источник = " .. source .. "\n" ..
        "|Путь    = " .. path .. "\n" ..
        "|Теги    = " .. tags .. "\n" ..
        "}}\n"
    )
end


function p.main(frame)
local byPath = findByPath(data, targetPath)
    local param = frame.args[1]
if byPath then
    local secondaryParam = frame.args[2]
return byPath
end


    -- Индекс путей
return "Ошибка: путь не найден"
    local spritePathIndex = createSpritePathIndex(data)
end


    if param == "repeat" then
return "Ошибка: неизвестный режим"
        return generateRepeatTemplate(data)
    elseif param == "path" and secondaryParam then
        for _, entry in ipairs(data) do
            local template = generateTemplate(entry, param, secondaryParam, data, spritePathIndex)
            if template then
                return template
            end
        end
        return nil
    elseif param == "image" and secondaryParam then
        for _, entry in ipairs(p.data) do
            if tostring(entry.id) == tostring(secondaryParam) then
                return getSpritePath(entry) or "Ошибка: Спрайт не найден."
            end
        end
        return "Ошибка: ID не найден."
    elseif param == "image" or param == "path" then
        local result = {}
        for _, entry in ipairs(data) do
            local template = generateTemplate(entry, param, secondaryParam, data, spritePathIndex)
            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

Текущая версия от 09:04, 29 марта 2026

Документация
-- Загрузка данных
local JsonPaths = require('Module:JsonPaths')
local spriteData = mw.loadData(JsonPaths.get("prototype/sprite.json"))

local p = {}

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 normalizeState(state)
	if state == nil then
		return nil
	end

	state = mw.text.trim(tostring(state))
	if state == "" then
		return nil
	end

	return state
end

-- Функция получения таблицы данных
local function getIdTable()
	if type(spriteData) == "table" and type(spriteData.id) == "table" then
		return spriteData.id
	end
	return nil
end

-- Функция для получения таблицы данных
function p.getData()
	return getIdTable() or {}
end

-- Функция получения пути спрайта:
-- 1) сначала entry.sprite
-- 2) потом первый layers[*].sprite
local function getSpritePath(entry)
	if not entry then
		return nil
	end

	if entry.sprite then
		return normalizeSpritePath(entry.sprite)
	end

	if type(entry.layers) == "table" then
		for _, layer in ipairs(entry.layers) do
			if layer and layer.sprite then
				return normalizeSpritePath(layer.sprite)
			end
		end
	end

	return nil
end

-- Проверка visible
local function isLayerVisible(layer)
	if not layer then
		return false
	end
	return layer.visible ~= false
end

-- Функция получения списка состояний с учётом переопределяющего sprite в слое
local function getSpriteStates(entry)
	local result = {}
	local spritePath = getSpritePath(entry)

	if entry and type(entry.layers) == "table" then
		for _, layer in ipairs(entry.layers) do
			if isLayerVisible(layer) and layer.state then
				table.insert(result, {
					state = tostring(layer.state),
					sprite = normalizeSpritePath(layer.sprite or spritePath)
				})
			end
		end
	elseif entry and entry.state and spritePath then
		table.insert(result, {
			state = tostring(entry.state),
			sprite = spritePath
		})
	end

	if #result == 0 and spritePath then
		table.insert(result, {
			state = "icon",
			sprite = spritePath
		})
	end

	return (#result > 0) and result or nil
end

local function findByPathAndState(data, targetPath, targetState)
	for entityId, entry in pairs(data) do
		if getSpritePath(entry) == targetPath then
			local states = getSpriteStates(entry)
			if states then
				for _, item in ipairs(states) do
					if normalizeState(item.state) == targetState then
						return entityId
					end
				end
			end
		end
	end

	return nil
end

local function findByPath(data, targetPath)
	for entityId, entry in pairs(data) do
		if getSpritePath(entry) == targetPath then
			return entityId
		end
	end

	return nil
end

-- Функция генерации шаблона по записи (mode: image, path, state)
function p.main(frame)
	local mode = frame.args[1]
	local id = frame.args[2]
	local stateArg = frame.args[3]

	if not mode or not id then
		return "Ошибка: отсутствует режим или ID"
	end

	local data = getIdTable()
	if not data then
		return "Ошибка: неверный формат JSON"
	end

	if mode == "image" or mode == "state" then
		local entry = data[id]
		if not entry then
			return "Ошибка: ID не найден"
		end

		if mode == "image" then
			local sprite = getSpritePath(entry)
			return sprite or "Ошибка: спрайт не найден"
		elseif mode == "state" then
			local states = getSpriteStates(entry)
			if not states then
				return ""
			end

			local baseUrl = JsonPaths.git() .. "/Resources/Textures/"
			local links = {}

			for _, item in ipairs(states) do
				local spritePath = item.sprite
				local stateName = item.state

				if spritePath then
					local url = baseUrl .. normalizeSpritePath(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

	if mode == "path" then
		local targetPath = normalizeSpritePath(id)
		local targetState = normalizeState(stateArg)

		if targetState then
			local byState = findByPathAndState(data, targetPath, targetState)
			if byState then
				return byState
			end
		end

		local byPath = findByPath(data, targetPath)
		if byPath then
			return byPath
		end

		return "Ошибка: путь не найден"
	end

	return "Ошибка: неизвестный режим"
end

return p