Модуль:Prototypes/Хранилище/Предмет
Материал из Space Station 14 Вики
Для документации этого модуля может быть создана страница Модуль:Prototypes/Хранилище/Предмет/doc
local p = {} -- Функции как локальные переменные local loadData, findDataById, formatContent, getContentsOutput, processNestedSelectors, getTableOutput, getContainedOutput, getChemOutput -- Функция для загрузки данных loadData = function(filePath) local page = mw.title.new(filePath) local content = page:getContent() return content and mw.text.jsonDecode(content) or nil end -- Поиск данных по ID findDataById = function(data, id) if not data then return nil end for _, item in ipairs(data) do if item.id == id then return item end end return nil end -- Форматирование одного содержимого formatContent = function(content) if not content.id then return "Ошибка: отсутствует id у элемента." end local name = string.format('{{#invoke:Entity Lookup|getname|%s}}', content.id) local image = string.format('%s.png', content.id) local amount = content.amount and string.format(" [%d]", content.amount) or "" local prob = "" -- Если есть weight, преобразуем его в prob if content.weight then content.prob = content.weight / 100 end -- Если есть prob, формируем отображение процента if content.prob then local percentage = content.prob * 100 if percentage >= 1 then prob = string.format(" <div>%d%%</div>", math.floor(percentage)) else prob = string.format(" <div>%g%%</div>", percentage) end end return string.format( '{{LinkСard|SideStyle=1|background-color=#d7d7ff0b|image=%s|name=%s%s%s {{#invoke:Prototypes/Хранилище/Предмет|main|framing|contained|%s}} }}', image, name, amount, prob, content.id ) end -- Получение содержимого getContentsOutput = function(contents) local result = '' for _, content in ipairs(contents) do result = result .. formatContent(content) end return result end -- Обработка вложенных таблиц processNestedSelectors = function(children) local result = '' for _, child in ipairs(children) do if child.id then result = result .. formatContent(child) elseif child["!type"] == "NestedSelector" and child.tableId then result = result .. getTableOutput(child.tableId) elseif child["!type"] == "GroupSelector" then result = result .. handleGroupSelector(child) end end return result end -- Обработка таблиц getTableOutput = function(tableId) local allSelectors = loadData('User:IanComradeBot/prototypes/AllSelector.json') local tableData = findDataById(allSelectors, tableId) if not tableData then return 'Таблица не найдена.' end if tableData['!type:GroupSelector'] and tableData['!type:GroupSelector'].children then local result = '' local groupSelectors = {} -- Группируем элементы по weight for _, child in ipairs(tableData['!type:GroupSelector'].children) do if child["!type"] == "GroupSelector" then local weight = tostring(child.weight or "default") groupSelectors[weight] = groupSelectors[weight] or {} table.insert(groupSelectors[weight], child) end end -- Генерация div для каждой группы for weight, groups in pairs(groupSelectors) do result = result .. string.format('<div class="together" id="%s">', weight) for _, group in ipairs(groups) do result = result .. handleGroupSelector(group) end result = result .. '</div>' end return result elseif tableData['!type:AllSelector'] and tableData['!type:AllSelector'].children then return processNestedSelectors(tableData['!type:AllSelector'].children) else return 'Таблица не содержит элементов.' end end -- Формирование списка содержащихся предметов или таблиц getContainedOutput = function(data, id, wrapped) local item = findDataById(data, id) if not item then return '' end local result = '' -- Обработка StorageFill if item.StorageFill and item.StorageFill.contents then result = result .. getContentsOutput(item.StorageFill.contents) -- Обработка EntityTableContainerFill elseif item.EntityTableContainerFill and item.EntityTableContainerFill.containers then local containers = item.EntityTableContainerFill.containers -- Обработка entity_storage if containers.entity_storage then local children = containers.entity_storage.children -- Если есть `children`, обрабатываем их if children then for _, child in ipairs(children) do if child["!type"] == "NestedSelector" and child.tableId then result = result .. handleNestedSelector(child) elseif child["!type"] == "GroupSelector" then result = result .. handleGroupSelector(child) elseif child["!type"] == "AllSelector" then result = result .. handleAllSelector(child) elseif child.id then result = result .. formatContent(child) end end end -- Если указан tableId if containers.entity_storage.tableId then result = result .. getTableOutput(containers.entity_storage.tableId) end end -- Обработка storagebase if containers.storagebase and containers.storagebase.tableId then result = result .. getTableOutput(containers.storagebase.tableId) end end return result end -- Обработка GroupSelector handleGroupSelector = function(groupSelector) local result = '' -- Проверка на существование children if not groupSelector.children then return "" end local weight = groupSelector.weight or "default" -- Начинаем формировать div для текущей группы result = result .. string.format('<div class="together" id="%s">', weight) -- Проходим по всем элементам children for _, child in ipairs(groupSelector.children) do -- Если это GroupSelector, рекурсивно обрабатываем if child["!type"] == "GroupSelector" then result = result .. handleGroupSelector(child) -- Рекурсивный вызов для вложенных групп elseif child.id then -- Для обычных элементов, с id, вызываем функцию formatContent result = result .. formatContent(child) else -- Обработка элементов без id (на всякий случай) result = result .. "<div>Ошибка: отсутствует id у элемента.</div>" end end -- Закрываем div для текущей группы result = result .. '</div>' return result end -- Обработка AllSelector handleAllSelector = function(allSelector) local result = '' if not allSelector.children then return result end for _, child in ipairs(allSelector.children) do if child["!type"] == "NestedSelector" and child.tableId then result = result .. handleNestedSelector(child) elseif child.id then result = result .. formatContent(child) end end return result end -- Обработка NestedSelector handleNestedSelector = function(nestedSelector) local result = '' local tableId = nestedSelector.tableId if not tableId then return result end -- Генерация классов для div local classes = {} if nestedSelector.rolls and nestedSelector.rolls.range then table.insert(classes, 'rolls-' .. tostring(nestedSelector.rolls.range):gsub(',', '-')) end if nestedSelector.prob then table.insert(classes, 'prob-' .. tostring(math.floor(nestedSelector.prob * 100)) .. 'p') end -- Обёртка div с классами local classString = table.concat(classes, ' ') result = result .. string.format('<div class="%s">', classString) result = result .. getTableOutput(tableId) result = result .. '</div>' return result end -- Формирование списка химии getChemOutput = function(data, id) local item = findDataById(data, id) if not item then return '' end local solutions = item.SolutionContainerManager and item.SolutionContainerManager.solutions if not solutions then return '' end local result = '<ul class="1">' for _, solution in pairs(solutions) do for _, reagent in ipairs(solution.reagents) do result = result .. string.format('<li>[[Химия#chem_%s|%s]] (%d ед.)</li>', reagent.ReagentId, reagent.ReagentId, reagent.Quantity) end end result = result .. '</ul>' return result end -- Обработка rolls processRolls = function(rolls) local result = '' if rolls.range then -- Если указан range local min, max = rolls.range:match("(%d+),%s*(%d+)") min, max = tonumber(min), tonumber(max) if min and max then result = string.format('Максимальное количество предметов: от %d до %d.', min, max) else result = 'Некорректный формат для range.' end elseif rolls.value then -- Если указано value result = string.format('Будет сгенерировано %d предметов.', rolls.value) else result = 'Не указан параметр rolls.' end return result end -- Основная функция модуля function p.main(frame) local mode = frame.args[1] local id = frame.args[2] if not id then return 'Не указан ID.' end local data = loadData('User:IanComradeBot/prototypes/fills/Item.json', 'items') if not data then return 'Не удалось загрузить данные.' end -- При режиме framing if mode == 'framing' then local subMode = frame.args[2] local id = frame.args[3] if not id then return 'Не указан ID для режима framing.' end if subMode == 'chem' then return frame:preprocess('{{СollapsibleMenu|' .. getChemOutput(data, id) .. '}}') elseif subMode == 'contained' then return frame:preprocess('{{СollapsibleMenu|' .. getContainedOutput(data, id, false) .. '}}') else return 'Неизвестный подрежим для framing: ' .. subMode end end -- При нормальном режиме if mode == 'chem' then return frame:preprocess(getChemOutput(data, id)) elseif mode == 'contained' then return frame:preprocess(getContainedOutput(data, id, false)) elseif mode == 'rolls' then local entity = findDataById(data, id) if not entity then return 'ID не найден в данных.' end if entity.EntityTableContainerFill then local containers = entity.EntityTableContainerFill.containers if containers.entity_storage and containers.entity_storage.rolls then return processRolls(containers.entity_storage.rolls) end end return 'Режим rolls не найден для этого ID.' else return 'Неизвестный режим: ' .. mode end end return p