(Title Case all the things and do lower-case comparisons to avoid casing issues) |
(Add vein and gas giant support, and use local variables) |
||
Line 11: | Line 11: | ||
Fractionate='Fractionator', |
Fractionate='Fractionator', |
||
Research='Matrix Lab', |
Research='Matrix Lab', |
||
Mine='Mining Machine', |
|||
Gas='Orbital Collector', |
|||
} |
} |
||
function funcs.recipesMaking(frame) |
function funcs.recipesMaking(frame) |
||
return recipesMakingName(frame:getParent().args[1], frame) |
|||
item = itemByName(name) |
|||
recipes = recipesMakingByID(item.ID) |
|||
return tableRecipes(recipes, frame) |
|||
end |
end |
||
function funcs.recipesMakingDirect(frame) |
function funcs.recipesMakingDirect(frame) |
||
return recipesMakingName(frame.args[1], frame) |
|||
end |
|||
item = itemByName(name) |
|||
recipes = recipesMakingByID(item.ID) |
|||
function recipesMakingName(name, frame) |
|||
local item = itemByName(name) |
|||
local recipes = recipesMakingByID(item.ID) |
|||
local vein = veinMakingByID(item.ID) |
|||
local gas = deduplicateGiants(gasGiantsMakingByID(item.ID)) |
|||
return tableRecipes(item, recipes, vein, gas, frame) |
|||
end |
end |
||
function funcs.recipesUsing(frame) |
function funcs.recipesUsing(frame) |
||
return recipesUsingName(frame:getParent().args[1], frame) |
|||
output = {} |
|||
name = frame:getParent().args[1] |
|||
item = itemByName(name) |
|||
components, buildings = recipesUsingByID(item.ID) |
|||
if next(components) then |
|||
table.insert(output, '=== Components ===') |
|||
table.insert(output, tableRecipes(components, frame)) |
|||
end |
|||
if next(buildings) then |
|||
table.insert(output, '=== Buildings ===') |
|||
table.insert(output, tableRecipes(buildings, frame)) |
|||
end |
|||
return table.concat(output, '\n') |
|||
end |
end |
||
function funcs.recipesUsingDirect(frame) |
function funcs.recipesUsingDirect(frame) |
||
return recipesUsingName(frame.args[1], frame) |
|||
output = {} |
|||
end |
|||
name = frame.args[1] |
|||
item = itemByName(name) |
|||
function recipesUsingName(name, frame) |
|||
components, buildings = recipesUsingByID(item.ID) |
|||
local output = {} |
|||
local item = itemByName(name) |
|||
local components, buildings = recipesUsingByID(item.ID) |
|||
if next(components) then |
if next(components) then |
||
table.insert(output, '=== Components ===') |
table.insert(output, '=== Components ===') |
||
table.insert(output, tableRecipes(components, frame)) |
table.insert(output, tableRecipes(item, components, nil, nil, frame)) |
||
end |
end |
||
if next(buildings) then |
if next(buildings) then |
||
table.insert(output, '=== Buildings ===') |
table.insert(output, '=== Buildings ===') |
||
table.insert(output, tableRecipes(buildings, frame)) |
table.insert(output, tableRecipes(item, buildings, nil, nil, frame)) |
||
end |
end |
||
return table.concat(output, '\n') |
return table.concat(output, '\n') |
||
end |
end |
||
function tableRecipes(recipes, frame) |
function tableRecipes(item, recipes, vein, gas, frame) |
||
result = {} |
local result = {} |
||
for _, recipe in pairs(recipes) do |
for _, recipe in pairs(recipes) do |
||
itemdata = {} |
local itemdata = {} |
||
itemdata.CraftTime = string.format('%s s', tostring(recipe.TimeSpend/60)) |
itemdata.CraftTime = string.format('%s s', tostring(recipe.TimeSpend/60)) |
||
for i, itemid in ipairs(recipe.Results) do |
for i, itemid in ipairs(recipe.Results) do |
||
Line 72: | Line 67: | ||
itemdata[string.format('In%dQty', i)] = tostring(recipe.ItemCounts[i]) |
itemdata[string.format('In%dQty', i)] = tostring(recipe.ItemCounts[i]) |
||
end |
end |
||
data = { |
local data = { |
||
Building = machines[recipe.Type], |
Building = titleCase(machines[recipe.Type]), |
||
Recipe = frame:expandTemplate{title='ItemRecipe', args=itemdata}, |
Recipe = frame:expandTemplate{title='ItemRecipe', args=itemdata}, |
||
} |
} |
||
Line 81: | Line 76: | ||
data.Replicator = 'No' |
data.Replicator = 'No' |
||
end |
end |
||
tech = technologyForRecipeID(recipe.ID) |
local tech = technologyForRecipeID(recipe.ID) |
||
if tech ~= nil then |
if tech ~= nil then |
||
data.Technology = titleCase(tech.Name) |
data.Technology = titleCase(tech.Name) |
||
Line 89: | Line 84: | ||
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=data}) |
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=data}) |
||
end |
end |
||
if vein then |
|||
prefix = frame:expandTemplate{title='ProductionChainTable/head', args={}} |
|||
local miner = itemByName(machines.Mine) |
|||
local minerTech = technologyForRecipeID(recipesMakingByID(miner.ID)[1].ID) |
|||
local vname = string.gsub(vein.Name, '%sVeins$', ' Vein') |
|||
local idata = { |
|||
In1 = titleCase(vname), |
|||
In1Qty = '1', |
|||
Out1 = titleCase(item.Name), |
|||
Out1Qty = '1', |
|||
CraftTime = '2 s', |
|||
} |
|||
local vrecipe = frame:expandTemplate{title='ItemRecipe', args=idata} |
|||
local veindata = { |
|||
Building = titleCase(miner.Name), |
|||
Replicator = 'Mine', |
|||
Technology = titleCase(minerTech.Name), |
|||
Recipe = vrecipe, |
|||
} |
|||
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=veindata}) |
|||
end |
|||
if gas then |
|||
local collector = itemByName(machines.Gas) |
|||
local collectorTech = technologyForRecipeID(recipesMakingByID(collector.ID)[1].ID) |
|||
for _, giant in pairs(gas) do |
|||
itemrecipe = { |
|||
CraftTime = '?', |
|||
In1 = titleCase(giant.DisplayName), |
|||
In1Qty = '', |
|||
} |
|||
for i, productID in ipairs(giant.GasItems) do |
|||
product = itemByID(productID) |
|||
itemrecipe[string.format('Out%d', i)] = titleCase(product.Name) |
|||
itemrecipe[string.format('Out%dQty', i)] = '1' |
|||
end |
|||
gasdata = { |
|||
Building = titleCase(collector.Name), |
|||
Replicator = 'Mine', |
|||
Technology = titleCase(collectorTech.Name), |
|||
Recipe = frame:expandTemplate{title='ItemRecipe', args=itemrecipe} |
|||
} |
|||
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=gasdata}) |
|||
end |
|||
end |
|||
local prefix = frame:expandTemplate{title='ProductionChainTable/head', args={}} |
|||
return string.format('%s\n%s\n|}', prefix, table.concat(result, '\n|-\n')) |
return string.format('%s\n%s\n|}', prefix, table.concat(result, '\n|-\n')) |
||
end |
end |
||
function itemByName(name) |
function itemByName(name) |
||
lame = string.lower(name) |
local lame = string.lower(name) |
||
for _, item in pairs(protosets.ItemProtoSet.dataArray) do |
for _, item in pairs(protosets.ItemProtoSet.dataArray) do |
||
if string.lower(item.Name) == lame then |
if string.lower(item.Name) == lame then |
||
Line 112: | Line 150: | ||
function recipesMakingByID(id) |
function recipesMakingByID(id) |
||
result = {} |
local result = {} |
||
for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do |
for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do |
||
for _, itemid in pairs(recipe.Results) do |
for _, itemid in pairs(recipe.Results) do |
||
Line 124: | Line 162: | ||
end |
end |
||
function recipesUsingByID(id) |
function recipesUsingByID(id) |
||
components = {} |
local components = {} |
||
buildings = {} |
local buildings = {} |
||
for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do |
for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do |
||
for _, itemid in pairs(recipe.Items) do |
for _, itemid in pairs(recipe.Items) do |
||
Line 150: | Line 188: | ||
end |
end |
||
return nil |
return nil |
||
end |
|||
function veinMakingByID(id) |
|||
for _, vein in pairs(protosets.VeinProtoSet.dataArray) do |
|||
if vein.MiningItem == id then |
|||
return vein |
|||
end |
|||
end |
|||
return nil |
|||
end |
|||
function gasGiantsMakingByID(id) |
|||
local giants = {} |
|||
for _, planet in pairs(protosets.ThemeProtoSet.dataArray) do |
|||
for _, item in pairs(planet.GasItems) do |
|||
if item == id then |
|||
table.insert(giants, planet) |
|||
break |
|||
end |
|||
end |
|||
end |
|||
return giants |
|||
end |
|||
function deduplicateGiants(giants) |
|||
local dedup = {} |
|||
for _, planet in pairs(giants) do |
|||
new = true |
|||
for _, exist in pairs(dedup) do |
|||
if string.lower(planet.DisplayName) == string.lower(exist.DisplayName) then |
|||
new = false |
|||
break |
|||
end |
|||
end |
|||
if new then table.insert(dedup, planet) end |
|||
end |
|||
return dedup |
|||
end |
end |
||
function titleCase(str) |
function titleCase(str) |
||
local start = string.gsub(str, '^%l', string.upper) |
|||
local title = string.gsub(start, '[-%s]%l', string.upper) |
|||
return title |
return title |
||
end |
end |
Revision as of 17:43, 27 April 2024
Source data for this module is stored at Module:GameData/protosets.json
Exported Functions
Each function in this module is exported twice: one as-is for use in templates, and once with a Direct suffix for use directly on pages using {{#invoke|GameData|functionDirect|...}}.
recipesMaking
Arguments: Item Name
Print recipes making an item, given by name. This produces a full table with headers.
Example invocation:
{{#invoke:GameData|recipesMakingDirect|Sulfuric Acid}}
Recipe | Building | Replicator? | Technology |
---|---|---|---|
![]() ![]() |
✖ |
recipesUsing
Arguments: Item Name
Print recipes using an item as an ingredient. Output is separated into two full tables: recipes which create components, and recipes which create buildings. This is selected by the CanBuild property of the produced items.
Example invocation:
{{#invoke:GameData|recipesUsingDirect|Copper Ingot}}
Components
Recipe | Building | Replicator? | Technology |
---|---|---|---|
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | N/A | |
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | N/A | |
![]() ![]() ![]() ![]() |
✖ | ||
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ |
Buildings
Recipe | Building | Replicator? | Technology |
---|---|---|---|
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ | ||
![]() ![]() ![]() ![]() |
✔ |
itemRecipes
Arguments: Item Name
Print recipes making an item. This does not produce a full table, and is intended for use in ItemInfo boxes such as at Graphene/ItemInfo.
itemField
Arguments: Item Name, Field Name
Print a field from an item, with the field to print as an argument. You can look at Module:GameData/protosets.json and scroll down or search (Ctrl+F) to the ItemProtoSet to browse fields.
Example invocation:
{{#invoke:GameData|itemFieldDirect|Magnetic Coil|Description}}
Script error: The function "itemFieldDirect" does not exist.
{{#invoke:GameData|itemFieldDirect|Hydrogen|StackSize}}
Script error: The function "itemFieldDirect" does not exist.
local funcs = {} local protosets = mw.loadJsonData('Module:GameData/protosets.json') local machines = { Smelt='Smelter', Assemble='Assembling Machine', Refine='Oil Refinery', Chemical='Chemical Plant', Exchange='Energy Exchanger', Particle='Miniature Particle Collider', PhotonStore='Ray Receiver', Fractionate='Fractionator', Research='Matrix Lab', Mine='Mining Machine', Gas='Orbital Collector', } function funcs.recipesMaking(frame) return recipesMakingName(frame:getParent().args[1], frame) end function funcs.recipesMakingDirect(frame) return recipesMakingName(frame.args[1], frame) end function recipesMakingName(name, frame) local item = itemByName(name) local recipes = recipesMakingByID(item.ID) local vein = veinMakingByID(item.ID) local gas = deduplicateGiants(gasGiantsMakingByID(item.ID)) return tableRecipes(item, recipes, vein, gas, frame) end function funcs.recipesUsing(frame) return recipesUsingName(frame:getParent().args[1], frame) end function funcs.recipesUsingDirect(frame) return recipesUsingName(frame.args[1], frame) end function recipesUsingName(name, frame) local output = {} local item = itemByName(name) local components, buildings = recipesUsingByID(item.ID) if next(components) then table.insert(output, '=== Components ===') table.insert(output, tableRecipes(item, components, nil, nil, frame)) end if next(buildings) then table.insert(output, '=== Buildings ===') table.insert(output, tableRecipes(item, buildings, nil, nil, frame)) end return table.concat(output, '\n') end function tableRecipes(item, recipes, vein, gas, frame) local result = {} for _, recipe in pairs(recipes) do local itemdata = {} itemdata.CraftTime = string.format('%s s', tostring(recipe.TimeSpend/60)) for i, itemid in ipairs(recipe.Results) do itemdata[string.format('Out%d', i)] = titleCase(itemByID(itemid).Name) itemdata[string.format('Out%dQty', i)] = tostring(recipe.ResultCounts[i]) end for i, itemid in ipairs(recipe.Items) do itemdata[string.format('In%d', i)] = titleCase(itemByID(itemid).Name) itemdata[string.format('In%dQty', i)] = tostring(recipe.ItemCounts[i]) end local data = { Building = titleCase(machines[recipe.Type]), Recipe = frame:expandTemplate{title='ItemRecipe', args=itemdata}, } if recipe.Handcraft then data.Replicator = 'Yes' else data.Replicator = 'No' end local tech = technologyForRecipeID(recipe.ID) if tech ~= nil then data.Technology = titleCase(tech.Name) else data.Technology = '' end table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=data}) end if vein then local miner = itemByName(machines.Mine) local minerTech = technologyForRecipeID(recipesMakingByID(miner.ID)[1].ID) local vname = string.gsub(vein.Name, '%sVeins$', ' Vein') local idata = { In1 = titleCase(vname), In1Qty = '1', Out1 = titleCase(item.Name), Out1Qty = '1', CraftTime = '2 s', } local vrecipe = frame:expandTemplate{title='ItemRecipe', args=idata} local veindata = { Building = titleCase(miner.Name), Replicator = 'Mine', Technology = titleCase(minerTech.Name), Recipe = vrecipe, } table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=veindata}) end if gas then local collector = itemByName(machines.Gas) local collectorTech = technologyForRecipeID(recipesMakingByID(collector.ID)[1].ID) for _, giant in pairs(gas) do itemrecipe = { CraftTime = '?', In1 = titleCase(giant.DisplayName), In1Qty = '', } for i, productID in ipairs(giant.GasItems) do product = itemByID(productID) itemrecipe[string.format('Out%d', i)] = titleCase(product.Name) itemrecipe[string.format('Out%dQty', i)] = '1' end gasdata = { Building = titleCase(collector.Name), Replicator = 'Mine', Technology = titleCase(collectorTech.Name), Recipe = frame:expandTemplate{title='ItemRecipe', args=itemrecipe} } table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=gasdata}) end end local prefix = frame:expandTemplate{title='ProductionChainTable/head', args={}} return string.format('%s\n%s\n|}', prefix, table.concat(result, '\n|-\n')) end function itemByName(name) local lame = string.lower(name) for _, item in pairs(protosets.ItemProtoSet.dataArray) do if string.lower(item.Name) == lame then return item end end error('No item named ' .. name) end function itemByID(id) for _, item in pairs(protosets.ItemProtoSet.dataArray) do if item.ID == id then return item end end error('No item with ID ' .. id) end function recipesMakingByID(id) local result = {} for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do for _, itemid in pairs(recipe.Results) do if itemid == id then table.insert(result, recipe) break end end end return result end function recipesUsingByID(id) local components = {} local buildings = {} for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do for _, itemid in pairs(recipe.Items) do if itemid == id then if itemByID(recipe.Results[1]).CanBuild then table.insert(buildings, recipe) else table.insert(components, recipe) end break end end end return components, buildings end function technologyForRecipeID(id) for _, tech in pairs(protosets.TechProtoSet.dataArray) do for _, recipeid in pairs(tech.UnlockRecipes) do if recipeid == id then return tech end end end return nil end function veinMakingByID(id) for _, vein in pairs(protosets.VeinProtoSet.dataArray) do if vein.MiningItem == id then return vein end end return nil end function gasGiantsMakingByID(id) local giants = {} for _, planet in pairs(protosets.ThemeProtoSet.dataArray) do for _, item in pairs(planet.GasItems) do if item == id then table.insert(giants, planet) break end end end return giants end function deduplicateGiants(giants) local dedup = {} for _, planet in pairs(giants) do new = true for _, exist in pairs(dedup) do if string.lower(planet.DisplayName) == string.lower(exist.DisplayName) then new = false break end end if new then table.insert(dedup, planet) end end return dedup end function titleCase(str) local start = string.gsub(str, '^%l', string.upper) local title = string.gsub(start, '[-%s]%l', string.upper) return title end return funcs