Module:Stonecutting: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 1: | Line 1: | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
-- Stone-cutter recipe carousel | -- Stone-cutter recipe carousel | ||
-- | -- Example: | ||
-- {{Stonecutting | -- {{Stonecutting | ||
-- |input=Stone | -- |input=Stone | ||
| Line 16: | Line 16: | ||
local p = {} | local p = {} | ||
local getArgs = require('Module:Arguments').getArgs | local getArgs = require( 'Module:Arguments' ).getArgs | ||
local trim = mw.text.trim | |||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
-- | -- turn {label,image,link} → thumbnail w/ link (32 px) | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
local function slotImage(label, image, link) | local function slotImage( label, image, link ) | ||
if not label or label == '' then return '' end | if not label or label == '' then return '' end | ||
local file = image ~= '' and image or ('Grid_' .. label .. '.png') | local file = ( image ~= '' ) and image or ( 'Grid_' .. label .. '.png' ) | ||
local | local target = ( link ~= '' ) and link or label | ||
return string.format( | return string.format( | ||
'[[File:%s|32px|class=pixelated|link=%s|alt=%s]]', | '[[File:%s|32px|class=pixelated|link=%s|alt=%s]]', | ||
file, | file, target, label | ||
) | ) | ||
end | end | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
-- build | -- build *one* frame (input + preview + output) | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
local function buildFrame(args, idx) | local function buildFrame( args, idx ) | ||
local | local inL , inI , inLn = args.input or args[1] or '', | ||
args['input-image'] or '', | |||
args['input-link'] or '' | |||
local outL | local outL = args[ 'output' .. idx ] or args[idx+1] or '' | ||
local outI | local outI = args[ 'output' .. idx .. '-image'] or '' | ||
local | local outLn = args[ 'output' .. idx .. '-link' ] or '' | ||
local html = mw.html.create('div'):addClass('sc-frame') | local html = mw.html.create( 'div' ):addClass( 'sc-frame' ) | ||
html:wikitext( '[[File:StonecutterGUI.png|180px|link=|alt=]]' ) | |||
html: | -- input (left) | ||
html:tag('div'):addClass('sc-slot') | |||
:css{ left = '11px', top = '50px' } | |||
:wikitext( slotImage( inL, inI, inLn ) ) | |||
-- | -- preview (top-centre) | ||
html:tag('div'):addClass('sc-slot') | |||
:css{ left = '56.5px', top = '23px' } | |||
:wikitext( slotImage( outL, outI, outLn ) ) | |||
-- output (right) | |||
html:tag('div'):addClass('sc-slot') | |||
:css{ left = '127px', top = '50px' } | |||
:wikitext( slotImage( outL, outI, outLn ) ) | |||
return tostring( html ) | |||
return tostring(html) | |||
end | end | ||
| Line 65: | Line 67: | ||
-- main entry | -- main entry | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
function p.carousel(frame) | function p.carousel( frame ) | ||
local args = getArgs(frame, {removeBlanks = false}) | local args = getArgs( frame, { removeBlanks = false } ) | ||
-- count outputs ( | -- count real outputs (skip blanks / whitespace) | ||
local count = 0 | |||
while true do | |||
local raw = args[ 'output' .. ( count + 1 ) ] or args[ count + 2 ] | |||
if not raw or trim( tostring( raw ) ) == '' then break end | |||
count = count + 1 | |||
end | |||
if count == 0 then | if count == 0 then | ||
return | return '<span style="color:red">Stonecutting: no outputs supplied</span>' | ||
end | end | ||
-- | ------------------------------------------------------------------ | ||
local outer = mw.html.create('div') | -- wrapper | ||
:addClass('stonecutting-carousel') | ------------------------------------------------------------------ | ||
:css{width = '180px', height = '131px', position = 'relative'} | local outer = mw.html.create( 'div' ) | ||
:addClass( 'stonecutting-carousel' ) | |||
:css{ width = '180px', height = '131px', position = 'relative' } | |||
for i = 1, count do | for i = 1, count do | ||
outer:wikitext(buildFrame(args, i)) | outer:wikitext( buildFrame( args, i ) ) | ||
end | end | ||
-- | -- base (static) stylesheet | ||
local base = frame:extensionTag( | |||
'templatestyles', '', { src = 'Template:Stonecutting/styles.css' } | |||
local | ) | ||
outer:wikitext( base ) | |||
local | ------------------------------------------------------------------ | ||
-- dynamic stylesheet (duration / delays) | |||
------------------------------------------------------------------ | |||
local dur = count * 4 -- seconds (4 s per recipe) | |||
local pct = 100 / count -- % slice per recipe | |||
local cssParts = {} | |||
table.insert( cssParts, | |||
table.insert( | string.format( | ||
'.stonecutting-carousel .sc-frame{animation:sc-cycle %ds steps(1) infinite;}', | |||
dur | |||
) | |||
) | |||
) | |||
for i = 1, count do | |||
for i = 1, count do | table.insert( cssParts, | ||
string.format( | |||
'.stonecutting-carousel .sc-frame:nth-child(%d){animation-delay:%ds;}', | |||
i, ( i - 1 ) * 4 | |||
) | |||
) | |||
end | |||
end | |||
table.insert( cssParts, | |||
table.insert( | string.format( | ||
'@keyframes sc-cycle{0%%{opacity:1;} %.2f%%{opacity:1;} %.2f%%{opacity:0;} 100%%{opacity:0;}}', | |||
pct, pct + 0.01 | |||
) | ) | ||
) | |||
local dyn = frame:extensionTag( | |||
'templatestyles', | |||
table.concat( cssParts, '' ), | |||
local | { lang = 'css' } | ||
) | |||
outer:wikitext( dyn ) | |||
) | |||
outer:wikitext( | |||
return tostring( outer ) | |||
end | end | ||
return p | return p | ||
Revision as of 22:00, 13 June 2025
Documentation for this module may be created at Module:Stonecutting/doc
------------------------------------------------------------
-- Stone-cutter recipe carousel
-- Example:
-- {{Stonecutting
-- |input=Stone
-- |input-image=Minecraft-stone.png
-- |input-link=https://minecraft.wiki/w/Stone
-- |output1=Slab
-- |output1-image=Minecraft-stoneslab.png
-- |output1-link=https://minecraft.wiki/w/Slab
-- |output2=Chisel
-- |output2-image=Pixelmon-chisel.png
-- |output2-link=Chisel
-- }}
------------------------------------------------------------
local p = {}
local getArgs = require( 'Module:Arguments' ).getArgs
local trim = mw.text.trim
------------------------------------------------------------------------
-- turn {label,image,link} → thumbnail w/ link (32 px)
------------------------------------------------------------------------
local function slotImage( label, image, link )
if not label or label == '' then return '' end
local file = ( image ~= '' ) and image or ( 'Grid_' .. label .. '.png' )
local target = ( link ~= '' ) and link or label
return string.format(
'[[File:%s|32px|class=pixelated|link=%s|alt=%s]]',
file, target, label
)
end
------------------------------------------------------------------------
-- build *one* frame (input + preview + output)
------------------------------------------------------------------------
local function buildFrame( args, idx )
local inL , inI , inLn = args.input or args[1] or '',
args['input-image'] or '',
args['input-link'] or ''
local outL = args[ 'output' .. idx ] or args[idx+1] or ''
local outI = args[ 'output' .. idx .. '-image'] or ''
local outLn = args[ 'output' .. idx .. '-link' ] or ''
local html = mw.html.create( 'div' ):addClass( 'sc-frame' )
html:wikitext( '[[File:StonecutterGUI.png|180px|link=|alt=]]' )
-- input (left)
html:tag('div'):addClass('sc-slot')
:css{ left = '11px', top = '50px' }
:wikitext( slotImage( inL, inI, inLn ) )
-- preview (top-centre)
html:tag('div'):addClass('sc-slot')
:css{ left = '56.5px', top = '23px' }
:wikitext( slotImage( outL, outI, outLn ) )
-- output (right)
html:tag('div'):addClass('sc-slot')
:css{ left = '127px', top = '50px' }
:wikitext( slotImage( outL, outI, outLn ) )
return tostring( html )
end
------------------------------------------------------------------------
-- main entry
------------------------------------------------------------------------
function p.carousel( frame )
local args = getArgs( frame, { removeBlanks = false } )
-- count real outputs (skip blanks / whitespace)
local count = 0
while true do
local raw = args[ 'output' .. ( count + 1 ) ] or args[ count + 2 ]
if not raw or trim( tostring( raw ) ) == '' then break end
count = count + 1
end
if count == 0 then
return '<span style="color:red">Stonecutting: no outputs supplied</span>'
end
------------------------------------------------------------------
-- wrapper
------------------------------------------------------------------
local outer = mw.html.create( 'div' )
:addClass( 'stonecutting-carousel' )
:css{ width = '180px', height = '131px', position = 'relative' }
for i = 1, count do
outer:wikitext( buildFrame( args, i ) )
end
-- base (static) stylesheet
local base = frame:extensionTag(
'templatestyles', '', { src = 'Template:Stonecutting/styles.css' }
)
outer:wikitext( base )
------------------------------------------------------------------
-- dynamic stylesheet (duration / delays)
------------------------------------------------------------------
local dur = count * 4 -- seconds (4 s per recipe)
local pct = 100 / count -- % slice per recipe
local cssParts = {}
table.insert( cssParts,
string.format(
'.stonecutting-carousel .sc-frame{animation:sc-cycle %ds steps(1) infinite;}',
dur
)
)
for i = 1, count do
table.insert( cssParts,
string.format(
'.stonecutting-carousel .sc-frame:nth-child(%d){animation-delay:%ds;}',
i, ( i - 1 ) * 4
)
)
end
table.insert( cssParts,
string.format(
'@keyframes sc-cycle{0%%{opacity:1;} %.2f%%{opacity:1;} %.2f%%{opacity:0;} 100%%{opacity:0;}}',
pct, pct + 0.01
)
)
local dyn = frame:extensionTag(
'templatestyles',
table.concat( cssParts, '' ),
{ lang = 'css' }
)
outer:wikitext( dyn )
return tostring( outer )
end
return p