|
|
| Line 1: |
Line 1: |
| -- Provides a standard way of interacting with data about goods, resources, and metaresources.
| | local Export = {} |
| local Resource = {} | | local resourceData = require("Module:ResourceData") |
|
| |
|
| -- A single resource with attributes like ID, name, category, etc.
| | local function recipeToText(recipe) |
| ---@class Resource
| | if not recipe or next(recipe) == nil then |
| ---@field _id ResourceID Unique ID code of the resource.
| | return "''None''" |
| ---@field _displayName ResourceName The display name in-game.
| | end |
| ---@field _description string The in-game descriptive text, including sprite icons, newlines, and escape characters.
| |
| ---@field _iconFilename Filename The file name of the icon for this resource.
| |
| ---@field _category CategoryResource Resource type from the info bar.
| |
| ---@field _tradingSellValue Coins Base value when selling to tradeposts.
| |
| ---@field _tradingBuyValue Coins Base cost when buying from Grand Market.
| |
|
| |
|
| -- The ID code of a good or resource.
| | local parts = {} |
| ---@alias ResourceID string
| |
|
| |
|
| -- The display name of a resource.
| | local i = 1 |
| ---@alias ResourceName string
| | while recipe["ingredient"..i] do |
| | | table.insert(parts, |
| -- Currency in-game.
| | string.format( |
| ---@alias Coins number
| | "%d [[File:%s|16px]] [[%s]]", |
| | | recipe["ingredient"..i.."_qty"], |
| -- The ID and amount of a good or service.
| | |
| ---@alias ResourcePair {_id: ResourceID, _amount: Amount}
| | recipe["ingredient"..i] |
| | | ) |
| -- The resource category based on the info bar.<br>
| | ) |
| -- Metaresources are categorized with trade goods.
| | i = i + 1 |
| ---@enum CategoryResource
| | end |
| local CATEGORY_RESOURCE = {
| |
| Materials = "Materials",
| |
| Food = "Food",
| |
| Drink = "Drink",
| |
| Ships = "Ships",
| |
| Equipment = "Equipment",
| |
| Weapons = "Weapons"
| |
| }
| |
| | |
| | |
| | |
| --#region Dependencies
| |
| | |
| local RESOURCES_DATA_FILE = "Module:Resources/resources_data"
| |
| | |
| local Wiki_Utility = require("Module:Wiki_Utility")
| |
| local icon = Wiki_Utility.renderIcon
| |
| local nowrap = Wiki_Utility.surroundWithNoWrap
| |
| local wrapClasses = Wiki_Utility.surroundWithClasses
| |
| local link = Wiki_Utility.renderWikiLink
| |
| local NBSP = Wiki_Utility.NBSP
| |
| local standards = Wiki_Utility.StandardizedSizes
| |
| local isValidIconSize = Wiki_Utility.isValidIconSize
| |
| | |
| --#endregion Dependencies
| |
| | |
| | |
| | |
| --#region Constants
| |
| | |
| local MIN_ICON_SIZE = 16
| |
| | |
| --#endregion Constants
| |
| | |
| | |
| | |
| --#region Private Members
| |
|
| |
|
| ---@type table<ResourceID, Resource>
| | if #parts == 0 then |
| local resourceData
| | return "''None''" |
| ---@type table<ResourceName, ResourceID>
| |
| local mapNamesToIDs
| |
| | |
| local function data()
| |
| if not resourceData then
| |
| mapNamesToIDs = {}
| |
| resourceData = mw.loadData(RESOURCES_DATA_FILE)
| |
| for id, resource in pairs(resourceData) do
| |
| mapNamesToIDs[resource._displayName] = id
| |
| end | | end |
| end
| |
| return resourceData
| |
| end
| |
|
| |
|
| -- Finds a resource by its display name.
| | return table.concat(parts, "<br/>") |
| ---@param resourceName ResourceName display name
| |
| ---@return Resource|nil foundResource or nil if not found
| |
| local function findName(resourceName)
| |
| local foundResource = nil
| |
| for _, resource in pairs(data()) do
| |
| if resource._displayName == resourceName then
| |
| foundResource = resource
| |
| break
| |
| end
| |
| end
| |
| return foundResource
| |
| end | | end |
|
| |
|
| -- Renders a link to the given resource's wiki page.<br>
| | function Export.resourceToWiki(resource) |
| -- If the specified iconSize is too small, the icon will be ommitted instead of drawn so small as to be unrecognizable.
| | local sourceText = {} |
| ---@param resource Resource must not be nil
| | local quantityText = {} |
| ---@param iconSize string|nil size of the icon including units, e.g., "x16px", or nil for default
| |
| ---@param needsIcon boolean|nil or nil for default
| |
| ---@param needsText boolean|nil or nil for default
| |
| ---@param targetElementID string|nil #name or #id of the DOM element to link directly to, if any
| |
| ---@return Wikitext wikitext
| |
| local function resourceLink(resource, iconSize, needsIcon, needsText, targetElementID)
| |
| iconSize = iconSize or standards.small
| |
| needsIcon = needsIcon or (needsIcon == nil and true)
| |
| needsText = needsText or (needsText == nil and true)
| |
| local wikitext = ""
| |
| local isValidSize, sizeN = isValidIconSize(iconSize)
| |
| if needsIcon and isValidSize and sizeN >= MIN_ICON_SIZE then
| |
| -- Make it a height if it's not already.
| |
| if not iconSize:match("^x") then
| |
| iconSize = "x" .. iconSize
| |
| end
| |
| local directLink = resource._displayName .. (targetElementID and ("" .. targetElementID) or "") | |
| wikitext = wikitext .. wrapClasses(icon(resource._iconFilename, iconSize, directLink, resource._displayName), "ats-link-resource", sizeN and sizeN < 23 and "ats-flag-small" or nil)
| |
| end
| |
| if (needsIcon and isValidSize and sizeN >= MIN_ICON_SIZE) and needsText then
| |
| wikitext = wikitext .. NBSP
| |
| end
| |
| if needsText then
| |
| wikitext = wikitext .. link(resource._displayName, resource._displayName, targetElementID)
| |
| end
| |
| return nowrap(wikitext)
| |
| end
| |
|
| |
|
| --#endregion Private Methods
| | for i = 1, 3 do |
| | local src = resource.production["source"..i] |
|
| |
|
| | if src and src ~= "" then |
| | table.insert(sourceText, "[[" .. src .. "]]") |
|
| |
|
| | local qty = resource.production["quantity"..i] or 0 |
| | table.insert(quantityText, tostring(qty)) |
| | end |
| | end |
|
| |
|
| --#region Public Methods
| | local recipe = recipeToText(resource.production.recipe1) |
|
| |
|
| -- Checks if the given ID is a valid resource ID.
| | return table.concat({ |
| ---@param id ResourceID
| | "| [[File: " .. resource.iconFile .. " |x96px]]", |
| ---@return boolean
| | "[[" .. resource.name .. "]]", |
| function Resource.isGood(id)
| | table.concat(sourceText, "<br/>"), |
| return data()[id] ~= nil
| | table.concat(quantityText, "<br/>"), |
| | recipe, |
| | tostring(resource.StackSize), |
| | tostring(resource.StackValue), |
| | }, " || ") |
| end | | end |
|
| |
|
| -- Finds a resource's ID by its display name.
| | function Export.tableToWiki() |
| ---@param displayName ResourceName
| |
| ---@return ResourceID|nil
| |
| function Resource.getID(displayName) | |
| data()
| |
| return mapNamesToIDs[displayName]
| |
| end
| |
|
| |
|
| -- Gets the specified resource's display name.
| | local rows = {} |
| ---@param id ResourceID
| |
| ---@return ResourceName
| |
| function Resource.getName(id)
| |
| return data()[id]._displayName
| |
| end
| |
|
| |
|
| -- Renders a table of pairs of resource IDs and amounts.
| | for _, resource in pairs(resourceData) do |
| ---@param pairsList ResourcePair[] array of pairs of resource IDs and amounts
| | table.insert(rows, Export.resourceToWiki(resource)) |
| ---@param iconSize string |nil size of the icon including any units, e.g., `20em` or `x16px` or assumes `px` if no units, or nil if not relevant
| |
| ---@vararg string|nil additional classes to add to the table, if any
| |
| ---@return Wikitext wikitext
| |
| function Resource.tableStack(pairsList, iconSize, ...)
| |
| local classes = {...}
| |
| -- quick check to see if amount column needed
| |
| local needsAmountColumn = false
| |
| for _, pair in ipairs(pairsList) do
| |
| if pair._amount and pair._amount ~= "" then
| |
| needsAmountColumn = true
| |
| end | | end |
| end
| |
| local wikitext = "{|" .. ((#classes > 0) and ("class=" .. table.concat(classes, " ")) or "") .. "\n"
| |
| for _, pair in ipairs(pairsList) do
| |
| local resource = data()[pair._id]
| |
| if not resource then return "[Resource table stack ID not found: " .. pair._id .. "]" end
| |
| wikitext = wikitext .. "|-\n"
| |
| wikitext = wikitext .. (needsAmountColumn and ("|style=text-align:right| " .. (pair._amount or "") .. "\n") or "")
| |
| wikitext = wikitext .. "| " .. resourceLink(resource, iconSize or standards.medium, true, true, "#Product") .. "\n"
| |
| end
| |
| return wikitext .. "|}"
| |
| end
| |
|
| |
|
| -- Renders a link to the given resource's wiki page by its ID.
| | return table.concat(rows, "\n|-\n") |
| ---@param resourceID ResourceID
| |
| ---@param iconSize string|nil size of the icon including units, e.g., "x16px" or nil for default
| |
| ---@param needsIcon boolean|nil or nil for default
| |
| ---@param needsText boolean|nil or nil for default | |
| ---@param targetElementID string|nil #name or #id of the DOM element to link directly to, if any
| |
| ---@return Wikitext wikitext
| |
| function Resource.resourceLinkByID(resourceID, iconSize, needsIcon, needsText, targetElementID)
| |
| return resourceLink(data()[resourceID], iconSize, needsIcon, needsText, targetElementID)
| |
| end | | end |
|
| |
|
| -- Resource_link template invokes this method from MediaWiki.
| | return Export |
| ---@param frame Frame MediaWiki template context
| |
| ---@return Wikitext wikitext wikitext markup to link to the resource's wiki page
| |
| function Resource.link(frame)
| |
| local name = frame.args.name or ""
| |
| if name == "" then
| |
| return "[Resource Link needs resource name]"
| |
| end
| |
| local iconSize = standards[frame.args.icon] or frame.args.icon or ""
| |
| local needsIcon = iconSize ~= "none"
| |
| -- Check if the size string is valid and doesn't represent a negative or too-large number.
| |
| if needsIcon and not isValidIconSize(iconSize) then
| |
| return "[Resource Link size not valid: " .. iconSize .. "]"
| |
| end
| |
| local display = frame.args.display or ""
| |
| if display ~= "" and display ~= "notext" then
| |
| return "[Resource Link display override not supported: " .. display .. "]"
| |
| end
| |
| local needsText = display ~= "notext"
| |
| local resource = findName(name)
| |
| if not resource then
| |
| return "[Resource not found: " .. name .. "]"
| |
| end
| |
| return resourceLink(resource, iconSize, needsIcon, needsText)
| |
| end
| |
| | |
| function Resource.stack(frame)
| |
| local parent = frame:getParent()
| |
| local args = parent and parent.args or frame.args
| |
| local iconSize = args.icon and (args.icon ~= "" and standards[args.icon] or standards.medium)
| |
| local classes = args.classes or ""
| |
| --@type ResourcePair[]
| |
| local pairsList = {}
| |
| -- handle the indeterminate number of unnamed parameters passed to the template, but skip empty ones
| |
| for _, pair in ipairs(args) do
| |
| pair = pair:match("^%s*(.-)%s*$")
| |
| if pair ~= "" then
| |
| local amount, name = pair:match("^(%d*)%s*(.+)$")
| |
| local resource = findName(name)
| |
| if not resource then
| |
| return "[Resource not found: " .. name .. "]"
| |
| end
| |
| pairsList[#pairsList + 1] = {_id = resource._id, _amount = amount}
| |
| end
| |
| end
| |
| if #pairsList == 0 then
| |
| return "[Resource stack needs at least one resource]"
| |
| end
| |
| return Resource.tableStack(pairsList, iconSize, classes)
| |
| end
| |
| | |
| --#endregion Public Methods
| |
| | |
| | |
| | |
| return Resource
| |
This module arranges resource data into a table, providing detailed stats as well as useful cost calculations.
It uses data from Module:ResourceData.
local Export = {}
local resourceData = require("Module:ResourceData")
local function recipeToText(recipe)
if not recipe or next(recipe) == nil then
return "''None''"
end
local parts = {}
local i = 1
while recipe["ingredient"..i] do
table.insert(parts,
string.format(
"%d [[File:%s|16px]] [[%s]]",
recipe["ingredient"..i.."_qty"],
recipe["ingredient"..i]
)
)
i = i + 1
end
if #parts == 0 then
return "''None''"
end
return table.concat(parts, "<br/>")
end
function Export.resourceToWiki(resource)
local sourceText = {}
local quantityText = {}
for i = 1, 3 do
local src = resource.production["source"..i]
if src and src ~= "" then
table.insert(sourceText, "[[" .. src .. "]]")
local qty = resource.production["quantity"..i] or 0
table.insert(quantityText, tostring(qty))
end
end
local recipe = recipeToText(resource.production.recipe1)
return table.concat({
"| [[File: " .. resource.iconFile .. " |x96px]]",
"[[" .. resource.name .. "]]",
table.concat(sourceText, "<br/>"),
table.concat(quantityText, "<br/>"),
recipe,
tostring(resource.StackSize),
tostring(resource.StackValue),
}, " || ")
end
function Export.tableToWiki()
local rows = {}
for _, resource in pairs(resourceData) do
table.insert(rows, Export.resourceToWiki(resource))
end
return table.concat(rows, "\n|-\n")
end
return Export