Module:CraftingTable: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 1: | Line 1: | ||
-- Module:CraftingTable | -- Module:CraftingTable | ||
-- Renders an animated crafting-table grid with optional per-slot and | |||
-- output-stack quantities. | |||
local p = {} | local p = {} | ||
local getArgs = require('Module:Arguments').getArgs | local getArgs = require('Module:Arguments').getArgs | ||
| Line 17: | Line 20: | ||
---------------------------------------------------------------------- | ---------------------------------------------------------------------- | ||
-- collect *all* numbered args for a slot (A1, A1-2 | -- collect *all* numbered args for a slot (A1, A1-2, …) | ||
-- returns { {label=…, image=…, link=…}, … }, qty | -- returns { {label=…, image=…, link=…}, … }, qty | ||
---------------------------------------------------------------------- | ---------------------------------------------------------------------- | ||
| Line 35: | Line 38: | ||
end | end | ||
end | end | ||
table.sort(items, function(a, b) return a.label < b.label end) -- deterministic | table.sort(items, function(a, b) return a.label < b.label end) -- deterministic | ||
return items, qty | return items, qty | ||
end | end | ||
---------------------------------------------------------------------- | ---------------------------------------------------------------------- | ||
-- | -- writes the expanded {{GridText}} overlay into *parent* | ||
---------------------------------------------------------------------- | ---------------------------------------------------------------------- | ||
local function putQtyOverlay(parent, colour, num) | local function putQtyOverlay(parent, frame, colour, num, left, bottom) | ||
local html = frame:expandTemplate{ title = 'GridText', args = { colour, num } } | |||
parent:tag('div') | parent:tag('div') | ||
:css{position='absolute', | :css{ | ||
position = 'absolute', | |||
:wikitext( | left = left or '0', | ||
bottom = bottom or '0', | |||
width = '32px', | |||
height = '14px', | |||
overflow = 'hidden' | |||
} | |||
:wikitext(html) | |||
end | end | ||
| Line 53: | Line 63: | ||
---------------------------------------------------------------------- | ---------------------------------------------------------------------- | ||
function p.grid(frame) | function p.grid(frame) | ||
local args = getArgs(frame, {removeBlanks = false}) | local args = getArgs(frame, { removeBlanks = false }) | ||
-- slot coordinates (input 3×3 + output) | -- slot coordinates (input 3×3 + output) | ||
local slots = { | local slots = { | ||
A1 = {14, 14}, A2 = {14, 50}, A3 = {14, 86}, | A1 = { 14, 14 }, A2 = { 14, 50 }, A3 = { 14, 86 }, | ||
B1 = {50, 14}, B2 = {50, 50}, B3 = {50, 86}, | B1 = { 50, 14 }, B2 = { 50, 50 }, B3 = { 50, 86 }, | ||
C1 = {86, 14}, C2 = {86, 50}, C3 = {86, 86}, | C1 = { 86, 14 }, C2 = { 86, 50 }, C3 = { 86, 86 }, | ||
Output = {202, 50}, | Output = { 202, 50 }, | ||
} | } | ||
| Line 70: | Line 80: | ||
if #items > 0 then | if #items > 0 then | ||
local holder = root:tag('div') | local holder = root:tag('div') | ||
:css | :css{ position='absolute', | ||
left = pos[1] .. 'px', | |||
top = pos[2] .. 'px', | |||
width='32px', height='32px' } | |||
if #items == 1 then | if #items == 1 then | ||
| Line 86: | Line 97: | ||
end | end | ||
-- per-slot quantity | -- per-slot quantity overlay | ||
if qty and qty > 1 then | if qty and qty > 1 then | ||
putQtyOverlay(holder, 'white', qty) | putQtyOverlay(holder, frame, 'white', qty) | ||
end | end | ||
end | end | ||
| Line 97: | Line 108: | ||
local tip = 'This recipe is shapeless; the ingredients may be placed in any arrangement in the crafting grid.' | local tip = 'This recipe is shapeless; the ingredients may be placed in any arrangement in the crafting grid.' | ||
root:tag('div') | root:tag('div') | ||
:css{position='absolute', left='135px', top='96px', | :css{ position='absolute', left='135px', top='96px', | ||
width='19px', height='15px' } | |||
:wikitext(string.format( | :wikitext(string.format( | ||
'<span title="%s">[[File:Shapeless.png|19px|class=pixelated|link=|alt=Shapeless recipe]]</span>', | '<span title="%s">[[File:Shapeless.png|19px|class=pixelated|link=|alt=Shapeless recipe]]</span>', | ||
| Line 105: | Line 116: | ||
end | end | ||
-- output-amount overlay | -- output-stack amount overlay | ||
if args.OA and tonumber(args.OA) and tonumber(args.OA) > 1 then | if args.OA and tonumber(args.OA) and tonumber(args.OA) > 1 then | ||
local box = root:tag('div') | local box = root:tag('div') | ||
:css{position='absolute', left='201px', top='71px', | :css{ position='absolute', left='201px', top='71px', | ||
width='64px', height='24px', overflow='hidden' } | |||
putQtyOverlay(box, 'white', args.OA) | putQtyOverlay(box, frame, 'white', args.OA, '33px', '0') -- centre over 64-px area | ||
end | end | ||
Revision as of 20:34, 24 June 2025
Documentation for this module may be created at Module:CraftingTable/doc
-- Module:CraftingTable
-- Renders an animated crafting-table grid with optional per-slot and
-- output-stack quantities.
local p = {}
local getArgs = require('Module:Arguments').getArgs
----------------------------------------------------------------------
-- helper : render a 32-px inventory-slot image
----------------------------------------------------------------------
local function slotImage(label, image, link)
if not label or label == '' then return '' end
local file = (image ~= '' and image) or ('Grid_' .. label .. '.png')
local tgt = (link ~= '' and link ) or ('Special:MyLanguage/' .. label)
return string.format(
'[[File:%s|32px|class=pixelated|link=%s|alt=%s]]',
file, tgt, label
)
end
----------------------------------------------------------------------
-- collect *all* numbered args for a slot (A1, A1-2, …)
-- returns { {label=…, image=…, link=…}, … }, qty
----------------------------------------------------------------------
local function collectItems(args, base)
local items, qty = {}, tonumber(args[base .. '-qty'])
for key, val in pairs(args) do
if mw.ustring.match(key, '^' .. base .. '$') or
mw.ustring.match(key, '^' .. base .. '%-%d+$') then
local label = val
if label and label ~= '' then
table.insert(items, {
label = label,
image = args[key .. '-image'] or '',
link = args[key .. '-link'] or ''
})
end
end
end
table.sort(items, function(a, b) return a.label < b.label end) -- deterministic
return items, qty
end
----------------------------------------------------------------------
-- writes the expanded {{GridText}} overlay into *parent*
----------------------------------------------------------------------
local function putQtyOverlay(parent, frame, colour, num, left, bottom)
local html = frame:expandTemplate{ title = 'GridText', args = { colour, num } }
parent:tag('div')
:css{
position = 'absolute',
left = left or '0',
bottom = bottom or '0',
width = '32px',
height = '14px',
overflow = 'hidden'
}
:wikitext(html)
end
----------------------------------------------------------------------
-- public entry – {{#invoke:CraftingTable|grid|…}}
----------------------------------------------------------------------
function p.grid(frame)
local args = getArgs(frame, { removeBlanks = false })
-- slot coordinates (input 3×3 + output)
local slots = {
A1 = { 14, 14 }, A2 = { 14, 50 }, A3 = { 14, 86 },
B1 = { 50, 14 }, B2 = { 50, 50 }, B3 = { 50, 86 },
C1 = { 86, 14 }, C2 = { 86, 50 }, C3 = { 86, 86 },
Output = { 202, 50 },
}
-- outer container (template already provides a relative parent)
local root = mw.html.create()
for slot, pos in pairs(slots) do
local items, qty = collectItems(args, slot)
if #items > 0 then
local holder = root:tag('div')
:css{ position='absolute',
left = pos[1] .. 'px',
top = pos[2] .. 'px',
width='32px', height='32px' }
if #items == 1 then
holder:wikitext(slotImage(items[1].label, items[1].image, items[1].link))
else
for i, it in ipairs(items) do
holder:tag('div')
:addClass('slot-frame')
:css('animation-duration', (#items * 2) .. 's')
:css('animation-delay', ((i - 1) * 2) .. 's')
:wikitext(slotImage(it.label, it.image, it.link))
end
end
-- per-slot quantity overlay
if qty and qty > 1 then
putQtyOverlay(holder, frame, 'white', qty)
end
end
end
-- shapeless icon
if args.shapeless and args.shapeless ~= '' then
local tip = 'This recipe is shapeless; the ingredients may be placed in any arrangement in the crafting grid.'
root:tag('div')
:css{ position='absolute', left='135px', top='96px',
width='19px', height='15px' }
:wikitext(string.format(
'<span title="%s">[[File:Shapeless.png|19px|class=pixelated|link=|alt=Shapeless recipe]]</span>',
mw.text.nowiki(tip)
))
end
-- output-stack amount overlay
if args.OA and tonumber(args.OA) and tonumber(args.OA) > 1 then
local box = root:tag('div')
:css{ position='absolute', left='201px', top='71px',
width='64px', height='24px', overflow='hidden' }
putQtyOverlay(box, frame, 'white', args.OA, '33px', '0') -- centre over 64-px area
end
return tostring(root)
end
return p