Module:UI: Difference between revisions

From Create: Minecraft Mod Wiki
Jump to navigation Jump to search
Create: Minecraft Mod Wiki>Vincent243
No edit summary
BoxWithout (talk | contribs)
m 129 revisions imported
 
(24 intermediate revisions by 3 users not shown)
Line 1: Line 1:


local slot = require( [[Module:Inventory slot]] ).slot
local slot = require( [[Module:Inventory slot]] ).slot
local addSlot = function( args, item, prefix, class, default )
local function addSlot(args, item, prefix, class, default)
local none, nostacksize
local none, nostacksize
prefix = prefix or ''
prefix = prefix or ''
if #prefix == 0 then
if #prefix == 0 then
none = 'none'
none = 'none'
nostacksize = ((item == '' or nil) and '') or (args and args[item] and args[item]:gsub( '[,%d]', '' ) or '')
nostacksize = ((item == '' or nil) and '') or (args and args[item] and args[item]:gsub('[,%d]', '') or '')
end
end
return slot{
return slot{
nostacksize or args[item], mod = args.Mod, link = none or args[prefix .. 'link'],
nostacksize or args[item], mod = args.Mod, link = none or args[prefix .. 'link'],
title = none or args[prefix .. 'title'], class = class, default = default,
title = none or args[prefix .. 'title'], class = class, default = default,
parsed = args.parsed
parsed = args.parsed, forcenum = args.forcenum
}
}
end
end
Line 18: Line 18:


-- Crafting table
-- Crafting table
function p.craftingTable( f )
function p.craftingTable(f)
local args = f
local args = f
if f == mw.getCurrentFrame() then
if f == mw.getCurrentFrame() then
Line 26: Line 26:
end
end
local body = mw.html.create( 'span' ):addClass( 'mcui mcui-Crafting_Table pixel-image' )
local body = mw.html.create('span'):addClass('mcui mcui-Crafting_Table pixel-image')
local input = body:tag( 'span' ):addClass( 'mcui-input' )
-- CUSTOM: changing grid to use <table> since wikia mobile doesn't support CSS
local input = body:tag('table'):addClass('mcui-input')
for num = 1, 3 do
for num = 1, 3 do
local row = input:tag( 'span' ):addClass( 'mcui-row' )
local row = input:tag('tr'):addClass('mcui-row')
for _, letter in ipairs{ 'A', 'B', 'C' } do
for _, letter in ipairs{ 'A', 'B', 'C' } do
row:wikitext( addSlot( args, letter .. num, 'I' ) )
    local td = row:tag('td')
td:wikitext(addSlot(args, letter .. num, 'I'))
end
end
end
end
local arrow = body:tag( 'span' ):addClass( 'mcui-arrow' ):tag( 'br' ):done()
local arrow = body:tag('span'):addClass('mcui-arrow'):tag('br'):done()
if args.arrow or '' ~= '' then
if args.arrow or '' ~= '' then
arrow:css(
arrow:css(
Line 45: Line 47:
body
body
:tag( 'span' )
:tag('span')
:addClass( 'mcui-output' )
:addClass('mcui-output')
:wikitext( addSlot( args, 'Output', 'O', 'invslot-large' ) )
:wikitext(addSlot(args, 'Output', 'O', 'invslot-large'))
local shapeless = args.shapeless or ''
local shapeless = args.shapeless or ''
local fixed = args.fixed or ''
local fixed = args.fixed or ''
if shapeless ~= '' or fixed ~= '' then
if shapeless ~= '' or fixed ~= '' then
local icon = body:tag( 'span' )
local icon = body:tag('span')
:addClass( 'mcui-icons' )
:addClass('mcui-icons')
:tag( 'span' )
:tag('span')
:tag( 'br' )
:tag('br')
:done()
:done()
if shapeless ~= '' then
if shapeless ~= '' then
icon:addClass( 'mcui-shapeless' )
icon:addClass('mcui-shapeless')
:attr( 'title',
:attr('title',
'This recipe is shapeless, the inputs may be placed in any arrangement in the crafting grid.'
'This recipe is shapeless, the inputs may be placed in any arrangement in the crafting grid.'
)
)
Line 69: Line 71:
end
end
icon:addClass( 'mcui-fixed' )
icon:addClass('mcui-fixed')
:attr( 'title',
:attr('title',
'This recipe is fixed, the input arrangement may not be moved or mirrored in the crafting grid' .. exceptFixed .. '.'
'This recipe is fixed, the input arrangement may not be moved or mirrored in the crafting grid' .. exceptFixed .. '.'
)
)
Line 76: Line 78:
end
end
return tostring( mw.html.create( 'div' ):node( body ) )
return tostring(mw.html.create('div'):node(body))
end
end


-- Furnace
-- Furnace
function p.furnace( f )
function p.furnace(f)
local args = f
local args = f
if f == mw.getCurrentFrame() then
if f == mw.getCurrentFrame() then
Line 88: Line 90:
end
end
local body = mw.html.create( 'span' ):addClass( 'mcui mcui-Furnace pixel-image' )
local body = mw.html.create('span'):addClass('mcui mcui-Furnace pixel-image')
local input = body:tag( 'span' ):addClass( 'mcui-input' )
local input = body:tag('span'):addClass('mcui-input')
input:wikitext( addSlot( args, 'Input', 'I' ) )
input:wikitext(addSlot(args, 'Input', 'I'))
local fuel = input:tag( 'span' ):addClass( 'mcui-fuel' ):tag( 'br' ):done()
local fuel = input:tag('span'):addClass('mcui-fuel'):tag('br'):done()
local fuelImg = args.FuelUsage or ''
local fuelImg = args.FuelUsage or ''
local burning = args.Input or '' ~= '' and args.Fuel or '' ~= ''
local burning = args.Input or '' ~= '' and args.Fuel or '' ~= ''
if not burning then
if not burning then
fuel:addClass( 'mcui-inactive' )
fuel:addClass('mcui-inactive')
if fuelImg ~= '' then
if fuelImg ~= '' then
fuelImg = fuelImg .. ' (in-active)'
fuelImg = fuelImg .. ' (in-active)'
Line 107: Line 109:
)
)
end
end
input:wikitext( addSlot( args, 'Fuel', 'F' ) )
input:wikitext(addSlot(args, 'Fuel', 'F'))
local arrow = body:tag( 'span' ):addClass( 'mcui-arrow' ):tag( 'br' ):done()
local arrow = body:tag('span'):addClass('mcui-arrow'):tag('br'):done()
local arrowImg = args.Progress or ''
local arrowImg = args.Progress or ''
if not burning or ( args.Output or '' ) == '' then
if not burning or (args.Output or '') == '' then
arrow:addClass( 'mcui-inactive' )
arrow:addClass('mcui-inactive')
if arrowImg ~= '' then
if arrowImg ~= '' then
arrowImg = arrowImg .. ' (in-active)'
arrowImg = arrowImg .. ' (in-active)'
Line 125: Line 127:
body
body
:tag( 'span' )
:tag('span')
:addClass( 'mcui-output' )
:addClass('mcui-output')
:wikitext( addSlot( args, 'Output', 'O', 'invslot-large' ) )
:wikitext(addSlot(args, 'Output', 'O', 'invslot-large'))
args.Experience = args.Experience or ''
if args.Experience ~= '' then
-- Converts commas to dots, removes all spaces and splits the arguments with semicolon.
local split = mw.text.split(string.gsub(args.Experience, '[ ,]', {[' '] = '', [','] = '.'}), ';', true)
local animated = body:tag('span'):attr('title', 'If there is a fractional part, it means the recipe has a chance equal to the fractional part of rewarding an additional XP point.')
:addClass('animated'):cssText('position:absolute;top:92px;left:108px;text-align:center;width:70px;')
local isNotFirst = true
for i, v in ipairs(split) do
assert(tonumber(v), 'Module:UI: "' .. v .. '" is not a valid number')
local xp = tonumber(v)
animated:tag('span')
:addClass(isNotFirst and 'animated-active' or nil)
:wikitext('<span style="display:inline-block;margin-top:3px;width:16px;height:16px;vertical-align:top;background-size:16px 16px;background-image:{{FileUrl|' .. experience_image(xp) .. '}}"></span>'
.. '<span style="display:inline-block;vertical-align:top;font-family:Minecraft;font-size:16px;color:#404040">'
.. ('&nbsp;' and xp > 72 or '') .. xp .. '</span>')
isNotFirst = false
end
end
return tostring( mw.html.create( 'div' ):node( body ) )
return tostring(mw.html.create('div'):node(body))
end
end


-- Brewing Stand
-- Brewing Stand
function p.brewingStand( f )
function p.brewingStand(f)
local args = f
local args = f
if f == mw.getCurrentFrame() then
if f == mw.getCurrentFrame() then
Line 160: Line 143:
end
end
local body = mw.html.create( 'span' ):addClass( 'mcui mcui-Brewing_Stand pixel-image' )
local body = mw.html.create('span'):addClass('mcui mcui-Brewing_Stand pixel-image')
local input = body:tag( 'span' ):addClass( 'mcui-input' )
local input = body:tag('span'):addClass('mcui-input')
input:tag( 'span' ):addClass( 'mcui-bubbling' ):tag( 'br' )
input:tag('span'):addClass('mcui-bubbling'):tag('br')
input:wikitext( addSlot( args, 'Input', 'I' ) )
input:wikitext(addSlot(args, 'Input', 'I'))
input:tag( 'span' ):addClass( 'mcui-arrow' ):tag( 'br' )
input:tag('span'):addClass('mcui-arrow'):tag('br')
if ( args.Input or '' ) == '' or
if (args.Input or '') == '' or
( ( args.Output1 or '' ) == '' and ( args.Output2 or '' ) == '' and ( args.Output3 or '' ) == '' )
((args.Output1 or '') == '' and (args.Output2 or '') == '' and (args.Output3 or '') == '')
then
then
input:addClass( 'mcui-inactive' )
input:addClass('mcui-inactive')
end
end
body:tag( 'span' ):addClass( 'mcui-paths' ):tag( 'br' )
body:tag('span'):addClass('mcui-paths'):tag('br')
local output = body:tag( 'span' ):addClass( 'mcui-output' )
local output = body:tag('span'):addClass('mcui-output')
for i = 1, 3 do
for i = 1, 3 do
output:wikitext( addSlot( args, 'Output' .. i, 'O' .. i, 'mcui-output' .. i ) )
output:wikitext(addSlot(args, 'Output' .. i, 'O' .. i, 'mcui-output' .. i))
end
end
return tostring( mw.html.create( 'div' ):node( body ) )
return tostring(mw.html.create('div'):node(body))
end
end


-- Stonecutter
-- Stonecutter
function p.stonecutter( f )
function p.stonecutter(f)
local args = f
local args = f
if f == mw.getCurrentFrame() then
if f == mw.getCurrentFrame() then
Line 191: Line 174:
end
end
local body = mw.html.create( 'span' ):addClass( 'mcui mcui-Stonecutter pixel-image' )
local body = mw.html.create('span'):addClass('mcui mcui-Stonecutter pixel-image')
local input = body:tag( 'span' ):addClass( 'mcui-input' )
local input = body:tag('span'):addClass('mcui-input')
input:wikitext( addSlot( args, 'Input', 'I' ) )
input:wikitext(addSlot(args, 'Input', 'I'))
local arrow = body:tag( 'span' ):addClass( 'mcui-stonecutterArrow' )
local arrow = body:tag('span'):addClass('mcui-stonecutterArrow')
if (args.arrow or '') ~= '' then
if (args.arrow or '') ~= '' then
arrow:css(
arrow:css(
Line 203: Line 186:
)
)
end
end
arrow:wikitext( addSlot( args, 'Output', '', 'invslot-plain mcui-stonecutterSprite' ) )
arrow:wikitext(addSlot(args, 'Output', '', 'invslot-plain invslot-noformat mcui-stonecutterSprite'))
body
body
:tag( 'span' )
:tag('span')
:addClass( 'mcui-output' )
:addClass('mcui-output')
:wikitext( addSlot( args, 'Output', 'O', 'invslot-large' ) )
:wikitext(addSlot(args, 'Output', 'O', 'invslot-large'))
return tostring(mw.html.create('div'):node(body))
end
 
-- Pre-1.20 Smithing Table
function p.legacySmithing(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
local body = mw.html.create('span'):addClass('mcui mcui-legacySmithing pixel-image')
body:tag('span'):addClass('mcui-text'):wikitext('Upgrade Gear'):done()
body:tag('span'):addClass('mcui-smithingHammer'):tag('br'):done()
local bottom = body:tag('div'):addClass('mcui-bottom')
local input = bottom:tag('span'):addClass('mcui-input')
input:wikitext(addSlot(args, 'Input1', 'I1'))
    input:tag('span'):addClass('mcui-plus'):done()
input:wikitext(addSlot(args, 'Input2', 'I2'))
return tostring( mw.html.create( 'div' ):node( body ) )
bottom:tag('span'):addClass('mcui-arrow'):tag('br'):done()
bottom
:tag('span')
:addClass('mcui-output')
:wikitext(addSlot(args, 'Output', 'O'))
return tostring(mw.html.create('div'):node(body))
end
 
-- Post-1.20 Smithing Table
function p.smithingTable(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
local body = mw.html.create('span'):addClass('mcui mcui-smithingTable pixel-image')
body:tag('span'):addClass('mcui-text'):wikitext('Upgrade Gear'):done()
body:tag('span'):addClass('mcui-smithingHammer'):tag('br'):done()
local bottom = body:tag('div'):addClass('mcui-bottom')
local input = bottom:tag('span'):addClass('mcui-input')
input:wikitext(addSlot(args, 'Input1', 'I1'))
input:wikitext(addSlot(args, 'Input2', 'I2'))
input:wikitext(addSlot(args, 'Input3', 'I3'))
bottom:tag('span'):addClass('mcui-arrow'):tag('br'):done()
bottom
:tag('span')
:addClass('mcui-output')
:wikitext(addSlot(args, 'Output', 'O'))
return tostring(mw.html.create('div'):node(body))
end
end


-- Loom
-- Loom
function p.loom( f )
function p.loom(f)
local args = f
local args = f
if f == mw.getCurrentFrame() then
if f == mw.getCurrentFrame() then
Line 222: Line 267:
end
end
local body = mw.html.create( 'span' ):addClass( 'mcui mcui-Loom pixel-image' )
local body = mw.html.create('span'):addClass('mcui mcui-Loom pixel-image')
local tapestry = body:tag( 'span' ):addClass( 'mcui-tapestry' )
local tapestry = body:tag('span'):addClass('mcui-tapestry')
if args.Banner and #args.Banner>0 then
if args.Banner and #args.Banner>0 then
tapestry:wikitext( addSlot( args, 'Banner', 'B', 'mcui-inputBanner' ) )
tapestry:wikitext(addSlot(args, 'Banner', 'B', 'mcui-inputBanner'))
end
end
if args.Dye and #args.Dye>0 then
if args.Dye and #args.Dye>0 then
tapestry:wikitext( addSlot( args, 'Dye', 'D', 'mcui-inputDye' ) )
tapestry:wikitext(addSlot(args, 'Dye', 'D', 'mcui-inputDye'))
end
end
if args.Pattern and #args.Pattern>0 then
if args.Pattern and #args.Pattern>0 then
tapestry:wikitext( addSlot( args, 'Pattern', 'P', 'mcui-inputPattern' ) )
tapestry:wikitext(addSlot(args, 'Pattern', 'P', 'mcui-inputPattern'))
end
end
tapestry:tag( 'span' ):tag( 'br' ):done()
tapestry:tag('span'):tag('br'):done()
local arrow = body:tag( 'span' ):addClass( 'mcui-loomArrow' )
local arrow = body:tag('span'):addClass('mcui-loomArrow')
if args.arrow or '' ~= '' then
if args.arrow or '' ~= '' then
arrow:css(
arrow:css(
Line 246: Line 291:
local bannerSprite
local bannerSprite
if sprite and #sprite>0 then
if sprite and #sprite>0 then
local animate = require( [[Module:AnimateSprite]] ).animate
local animate = require([[Module:AnimateSprite]]).animate
bannerSprite = animate{
bannerSprite = animate{
args.Sprite,
args.Sprite,
Line 256: Line 301:
arrow
arrow
:tag( 'span' )
:tag('span')
:addClass( 'mcui-bannerSprite' )
:addClass('mcui-bannerSprite')
:wikitext( bannerSprite )
:wikitext(bannerSprite)
body
body
:tag( 'span' )
:tag('span')
:addClass( 'mcui-output' )
:addClass('mcui-output')
:wikitext( addSlot( args, 'Output', 'O', 'invslot-large' ) )
:wikitext(addSlot(args, 'Output', 'O', 'invslot-large'))
return tostring( mw.html.create( 'div' ):node( body ) )
return tostring(mw.html.create('div'):node(body))
end
end


-- Grindstone
-- Grindstone
function p.grindstone( f )
function p.grindstone(f)
local args = f
local args = f
if f == mw.getCurrentFrame() then
if f == mw.getCurrentFrame() then
Line 277: Line 322:
end
end
local body = mw.html.create( 'span' ):addClass( 'mcui mcui-Grindstone pixel-image' )
local body = mw.html.create('span'):addClass('mcui mcui-Grindstone pixel-image')
local grindstone = body:tag( 'span' ):addClass( 'mcui-grindstone' )
local grindstone = body:tag('span'):addClass('mcui-grindstone')
grindstone:wikitext( addSlot( args, 'Input1', 'I1', 'mcui-input1' ) )
grindstone:wikitext(addSlot(args, 'Input1', 'I1', 'mcui-input1'))
grindstone:wikitext( addSlot( args, 'Input2', 'I2', 'mcui-input2' ) )
grindstone:wikitext(addSlot(args, 'Input2', 'I2', 'mcui-input2'))
local arrow = body:tag( 'span' ):addClass( 'mcui-arrow' )
local arrow = body:tag('span'):addClass('mcui-arrow')
if args.arrow or '' ~= '' then
if args.arrow or '' ~= '' then
arrow:css(
arrow:css(
Line 291: Line 336:
body
body
:tag( 'span' )
:tag('span')
:addClass( 'mcui-output' )
:addClass('mcui-output')
:wikitext( addSlot( args, 'Output', 'O', 'invslot-large' ) )
:wikitext(addSlot(args, 'Output', 'O', 'invslot-large'))
return tostring( mw.html.create( 'div' ):node( body ) )
return tostring(mw.html.create('div'):node(body))
end
end
-- Smithing Table
-- Crushing Wheel
function p.smithing (f)  
function p.crushingWheel(f)
local args = f
local args = f
if f == mw.getCurrentFrame() then
if f == mw.getCurrentFrame() then
args = f:getParent().args
args = f:getParent().args
else
else
f = mw.getCurrentFrame()
f = mw.getCurrentFrame()
end
end
return tostring( mw.html.create( 'div' ):node( body ) )
return p.commonMachine{
args,
manyInputs=false,
manyOutputs=true,
allowChance=true,
slot='Crushing',
paddingtop = '14px',
paddingtop2 = '14px'
}
end
 
--Bulk Washing
function p.bulkWashing(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
return p.commonMachine{
args,
manyInputs=false,
manyOutputs=true,
allowChance=true,
slot='Bulk Washing',
paddingtop = '14px',
paddingtop2 = '14px'
}
end
--Bulk Haunting
function p.bulkHaunting(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
return p.commonMachine{
args,
manyInputs=false,
manyOutputs=true,
allowChance=true,
slot='Bulk Haunting',
paddingtop = '14px'
}
end
--Bulk Smoking
function p.bulkSmoking(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
return p.commonMachine{
args,
manyInputs=false,
manyOutputs=false,
allowChance=false,
slot='Bulk Smoking',
paddingtop = '14px'
}
end
--Bulk Blasting
function p.bulkBlasting(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
return p.commonMachine{
args,
manyInputs=false,
manyOutputs=false,
allowChance=false,
slot='Bulk Blasting',
paddingtop = '14px'
}
end
--Deploying
function p.deploying(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
return p.commonMachine{
args,
manyInputs=true,
manyOutputs=false,
allowChance=false,
slot='Deploying',
paddingtop = '14px'
}
end
--Manual Item Application
function p.manualApplication(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
return p.commonMachine{
args,
manyInputs=true,
manyOutputs=false,
allowChance=false,
slot='Manual Item Application',
paddingtop = '14px'
}
end
--Mechanical Mixer
function p.mechanicalMixer(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
if args.type:lower() == 'crafting' or args.type:lower() == 'shapeless' then
return p.commonMachine{
args,
manyInputs=true,
manyOutputs=false,
allowChance=false,
slot='Mechanical Mixer Crafting',
paddingtop = '14px'
}
elseif args.type:lower() == 'mixing' then
return p.commonMachine{
args,
manyInputs=true,
manyOutputs=false,
allowChance=false,
slot='Mechanical Mixer Mixing',
lowerslot=args.Heating,
paddingtop = args.Heating and '6px' or '14px',
paddingbottom = '0'
}
elseif args.type:lower() == 'brewing' then
return p.commonMachine{
args,
manyInputs=true,
manyOutputs=false,
allowChance=false,
slot='Mechanical Mixer Brewing',
lowerslot=args.Heating,
paddingtop = args.Heating and '6px' or '14px',
paddingbottom = '0'
}
else
return '<strong><font color="red">Template error: invalid type specified</font></strong>'
end
end
--Mechanical Press
function p.mechanicalPress(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
if args.type:lower() == 'crafting' or args.type:lower() == 'packing' then
return p.commonMachine{
args,
inputType = 'grid',
manyOutputs=false,
allowChance=false,
isOneItemType=true,
slot='Mechanical Press Crafting',
paddingtop = '10px',
paddingbottom = '6px',
paddingtop2 = '6px',
}
elseif args.type:lower() == 'compacting' then
return p.commonMachine{
args,
manyInputs=true,
manyOutputs=false,
allowChance=false,
slot='Mechanical Press Compacting',
paddingtop = '14px',
}
elseif args.type:lower() == 'pressing' then
return p.commonMachine{
args,
manyInputs=false,
manyOutputs=false,
allowChance=false,
slot='Mechanical Press Pressing',
paddingtop = '14px',
}
else
return '<strong><font color="red">Template error: invalid type specified</font></strong>'
end
end
-- Millstone
function p.millstone(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
return p.commonMachine{
args,
manyInputs=false,
manyOutputs=true,
allowChance=true,
slot='Milling',
paddingtop = '14px',
paddingtop2 = '20px'
}
end
-- Mechanical Crafter
function p.mechanicalCrafter(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
return p.commonMachine{
args,
inputType = 'mechanicalCrafter',
manyInputs=false,
manyOutputs=false,
allowChance=false,
slot='Mechanical Crafting',
paddingbottom = '6px',
largeOutputSlot = true,
}
end
--Mechanical Saw
function p.mechanicalSaw(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
return p.commonMachine{
args,
manyInputs=false,
manyOutputs=true,
allowChance=false,
slot='Sawing',
paddingtop = '14px'
}
end
--Spout
function p.spout(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
return p.commonMachine{
args,
manyInputs=true,
manyOutputs=false,
allowChance=false,
slot='Filling by Spout',
paddingtop = '14px'
}
end
--Sandpaper
function p.sandpaper(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
return p.commonMachine{
args,
manyInputs=false,
manyOutputs=false,
allowChance=false,
slot='Sandpaper Polishing;Sandpaper Polishing (Red)',
paddingtop = '14px'
}
end
-- Sequenced Assembly (WIP)
function p.sequencedAssembly(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
local body = mw.html.create('span'):addClass('mcui mcui-Sequenced_Assembly pixel-image')
local input = body:tag('span'):addClass('mcui-input')
input:wikitext(addSlot(args, 'Input', 'I'))
local Sequence = ''
local Sequence1 = input:tag('span'):addClass('mcui-sequence1'):done()
local Sequence2 = input:tag('span'):addClass('mcui-sequence2'):done()
local Sequence3 input:tag('span'):addClass('mcui-sequence3'):done()
end
-- Common Machines
function p.commonMachine(options)
local args = options[1]
local body = mw.html.create('span'):addClass('mcui mcui-Common_Machines pixel-image')
local input
local i = 1
local totalItems = 0
local inputRows = 0
local outputRows = 0
if options.inputType == 'grid' or options.inputType == 'mechanicalCrafter' then
input = body:tag('table'):addClass('mcui-input')
if options.inputType == 'mechanicalCrafter' then
for num = 1, 5 do
local rowHasEntry = false
for _, letter in ipairs{ 'A', 'B', 'C', 'D', 'E' } do
if  args[letter..num] and mw.text.trim(args[letter..num]) ~= '' then
rowHasEntry = true
break
end
end
if rowHasEntry then
inputRows = inputRows + 1
local row = input:tag('tr'):addClass('mcui-row')
for letternum, letter in ipairs{ 'A', 'B', 'C', 'D', 'E' } do
if not args.gridwidth or letternum <= tonumber(args.gridwidth) then
    local td = row:tag('td')
    if args[letter..num] and mw.text.trim(args[letter..num]) ~= '' then
    td:wikitext(slot{args[letter..num]})
    totalItems = totalItems + 1
    isEmptyRow = false
    else
    td:wikitext(slot{
    nil,
    class='invslot-noformat'
    })
    end
end
end
end
end
local paddingtops = {
[0] = '0',
[1] = '18px',
[2] = '8px',
[3] = '6px',
[4] = '6px',
[5] = '6px',
}
options.paddingtop = paddingtops[inputRows]
elseif args.smallgrid then
for num = 1, 2 do
local row = input:tag('tr'):addClass('mcui-row')
inputRows = inputRows + 1
for _, letter in ipairs{ 'A', 'B' } do
    local td = row:tag('td')
local itemArg = options.isOneItemType and 'Input' or letter..num
td:wikitext(slot{args[itemArg]})
end
end
else
for num = 1, 3 do
local row = input:tag('tr'):addClass('mcui-row')
inputRows = inputRows + 1
for _, letter in ipairs{ 'A', 'B', 'C' } do
    local td = row:tag('td')
local itemArg = options.isOneItemType and 'Input' or letter..num
td:wikitext(slot{args[itemArg]})
end
end
end
elseif options.inputType == 'normal' or not options.inputType then
input = body
:tag('table')
:addClass('mcui-input')
:tag('tr')
:addClass('mcui-row')
while args['Input'..i] or args['I'..i] or (i == 1 and (args['Input'] or args['I'])) do
local iItem = options.manyInputs and (args['Input'..i] or args['I'..i]) or nil
local item = i == 1 and (args['Input'] or args['I'] or iItem) or iItem
input = addSlotElement(input, item)
i = i + 1
end
end
local middle = body
:tag('div')
:addClass('mcui-middle')
middle:tag('div')
:wikitext(slot{
table.concat{
options.slot, ',', totalItems,
(totalItems > 0 and table.concat{'[&7Requires ', totalItems, ' Crafters!]'} or ''),
},
class = 'invslot-noformat'
})
:done()
middle
:tag('div')
:addClass(options.arrowclass or 'mcui-arrow-long')
:done()
if options.lowerslot then
middle:tag('div')
:css{
['position']='relative',
['bottom']='8px',
}
:wikitext(slot{
options.lowerslot,
class = 'invslot-noformat'
})
:done()
end
local output = body
:tag('table')
:addClass('mcui-output')
local isChance = false
if options.allowChance == nil then options.allowChance = true end
if options.allowChance then
for j=1,50,1 do
if args['Chance'..j] or args['C'..j] then
isChance = true
break
end
end
end
if isChance then
output:css{['top']='9px'}
body:css{['padding-bottom']='9px'}
end
i = 1
local rows = {}
local j = 1
while args['Output'..i] or args['O'..i] or (i == 1 and (args['Output'] or args['O'])) do
if i % 5 == 1 then
rows[j] = output:tag('tr'):addClass('mcui-row')
outputRows = outputRows + 1
end
local iItem = options.manyOutputs and (args['Output'..i] or args['O'..i]) or nil
local item = i == 1 and (args['Output'] or args['O'] or iItem) or iItem
local chance = i == 1 and (args['Chance'] or args['C'] or args['Chance'..i] or args['C'..i]) or (args['Chance'..i] or args['C'..i])
rows[j] = addSlotElement(rows[j], item, chance, isChance and options.allowChance, options.largeOutputSlot)
i = i + 1
if i % 5 == 1 then j = j + 1 end
end
if isChance then
if options.paddingbottom then
body:css{
['padding-top'] = options.paddingtop2 or '20px',
['padding-bottom'] = options.paddingbottom or '0'
}
else
body:css{['padding-top'] = options.paddingtop2 or '20px'}
end
else
if options.paddingbottom then
body:css{
['padding-top'] = options.paddingtop or '14px',
['padding-bottom'] = options.paddingbottom or '0'
}
else
body:css{['padding-top'] = options.paddingtop or '14px'}
end
end
if options.lowerslot then
middle:css{['bottom']='0'}
else
local bottoms = {
[0] = '11px',
[1] = '12px',
[2] = '5px',
[3] = '-14px',
[4] = '-31px',
[5] = '-48px',
}
middle:css{['bottom']=bottoms[inputRows > outputRows and inputRows or outputRows] or options.bottom}
end
return tostring(mw.html.create('div'):node(body))
end
function addSlotElement(element, item, chance, allowChance, largeOutputSlot)
if allowChance then
element
:css{['top']='9px'}
:tag('td')
:tag('span')
:wikitext(slot{item})
:done()
:tag('span')
:addClass(chance and 'mcui-text' or 'mcui-text mcui-text-nondisplay')
:wikitext(chance or 'nil')
:done()
:done()
:done()
else
element
:tag('td')
:wikitext(slot{item, class=largeOutputSlot and 'invslot-large' or nil})
:done()
:done()
end
return element
end
 
function p.slotList(f)
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
local maxWidth = tonumber(args.maxwidth or args.width or args.w) or 6
local wikitable = mw.html.create('table')
:addClass('mcui-output')
local i = 1
while args[i] and mw.text.trim(args[i]) ~= '' do
local row = wikitable:tag('tr'):addClass('mcui-row')
local j = 1
while args[i] and mw.text.trim(args[i]) ~= '' and j <= maxWidth do
row:tag('td'):wikitext(slot{args[i], class='invslot-noformat'}):done()
i = i + 1
j = j + 1
end
end
return tostring(wikitable)
end
end
return p
return p

Latest revision as of 21:59, 14 February 2025

Documentation for this module may be created at Module:UI/doc

local slot = require( [[Module:Inventory slot]] ).slot
local function addSlot(args, item, prefix, class, default)
	local none, nostacksize
	prefix = prefix or ''
	if #prefix == 0 then
		none = 'none'
		nostacksize = ((item == '' or nil) and '') or (args and args[item] and args[item]:gsub('[,%d]', '') or '')
	end
	return slot{
		nostacksize or args[item], mod = args.Mod, link = none or args[prefix .. 'link'],
		title = none or args[prefix .. 'title'], class = class, default = default,
		parsed = args.parsed, forcenum = args.forcenum
	}
end

local p = {}

-- Crafting table
function p.craftingTable(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	
	local body = mw.html.create('span'):addClass('mcui mcui-Crafting_Table pixel-image')
	
	-- CUSTOM: changing grid to use <table> since wikia mobile doesn't support CSS
	local input = body:tag('table'):addClass('mcui-input')
	for num = 1, 3 do
		local row = input:tag('tr'):addClass('mcui-row')
		for _, letter in ipairs{ 'A', 'B', 'C' } do
		    local td = row:tag('td')
			td:wikitext(addSlot(args, letter .. num, 'I'))
		end
	end
	
	local arrow = body:tag('span'):addClass('mcui-arrow'):tag('br'):done()
	if args.arrow or '' ~= '' then
		arrow:css(
			'background-image',
			'{{FileUrl|' .. args.arrow .. ' (' .. args.Mod .. ').png}}'
		)
	end
	
	body
		:tag('span')
			:addClass('mcui-output')
			:wikitext(addSlot(args, 'Output', 'O', 'invslot-large'))
	
	local shapeless = args.shapeless or ''
	local fixed = args.fixed or ''
	if shapeless ~= '' or fixed ~= '' then
		local icon = body:tag('span')
			:addClass('mcui-icons')
			:tag('span')
				:tag('br')
			:done()
		if shapeless ~= '' then
			icon:addClass('mcui-shapeless')
				:attr('title',
					'This recipe is shapeless, the inputs may be placed in any arrangement in the crafting grid.'
				)
		elseif fixed ~= '' then
			local notFixed = args.notfixed or ''
			local exceptFixed = ''
			if notFixed ~= '' then
				exceptFixed = '; except for ' .. notFixed .. ', which can go anywhere'
			end
			
			icon:addClass('mcui-fixed')
				:attr('title',
					'This recipe is fixed, the input arrangement may not be moved or mirrored in the crafting grid' .. exceptFixed .. '.'
				)
		end
	end
	
	return tostring(mw.html.create('div'):node(body))
end

-- Furnace
function p.furnace(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	
	local body = mw.html.create('span'):addClass('mcui mcui-Furnace pixel-image')
	
	local input = body:tag('span'):addClass('mcui-input')
	input:wikitext(addSlot(args, 'Input', 'I'))
	local fuel = input:tag('span'):addClass('mcui-fuel'):tag('br'):done()
	local fuelImg = args.FuelUsage or ''
	local burning = args.Input or '' ~= '' and args.Fuel or '' ~= ''
	if not burning then
		fuel:addClass('mcui-inactive')
		if fuelImg ~= '' then
			fuelImg = fuelImg .. ' (in-active)'
		end
	end
	if fuelImg ~= '' then
		fuel:css(
			'background-image',
			'{{FileUrl|' .. fuelImg .. ' (' .. args.Mod .. ').png}}'
		)
	end
	input:wikitext(addSlot(args, 'Fuel', 'F'))
	
	local arrow = body:tag('span'):addClass('mcui-arrow'):tag('br'):done()
	local arrowImg = args.Progress or ''
	if not burning or (args.Output or '') == '' then
		arrow:addClass('mcui-inactive')
		if arrowImg ~= '' then
			arrowImg = arrowImg .. ' (in-active)'
		end
	end
	if arrowImg ~= '' then
		arrow:css(
			'background-image',
			'{{FileUrl|' .. arrowImg .. ' Progress (' .. args.Mod .. ').png}}'
		)
	end
	
	body
		:tag('span')
			:addClass('mcui-output')
			:wikitext(addSlot(args, 'Output', 'O', 'invslot-large'))
	
	return tostring(mw.html.create('div'):node(body))
end

-- Brewing Stand
function p.brewingStand(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	
	local body = mw.html.create('span'):addClass('mcui mcui-Brewing_Stand pixel-image')
	
	local input = body:tag('span'):addClass('mcui-input')
	input:tag('span'):addClass('mcui-bubbling'):tag('br')
	input:wikitext(addSlot(args, 'Input', 'I'))
	input:tag('span'):addClass('mcui-arrow'):tag('br')
	if (args.Input or '') == '' or
		((args.Output1 or '') == '' and (args.Output2 or '') == '' and (args.Output3 or '') == '')
	then
		input:addClass('mcui-inactive')
	end
	
	body:tag('span'):addClass('mcui-paths'):tag('br')
	
	local output = body:tag('span'):addClass('mcui-output')
	for i = 1, 3 do
		output:wikitext(addSlot(args, 'Output' .. i, 'O' .. i, 'mcui-output' .. i))
	end
	
	return tostring(mw.html.create('div'):node(body))
end

-- Stonecutter
function p.stonecutter(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	
	local body = mw.html.create('span'):addClass('mcui mcui-Stonecutter pixel-image')
	
	local input = body:tag('span'):addClass('mcui-input')
	input:wikitext(addSlot(args, 'Input', 'I'))
	
	local arrow = body:tag('span'):addClass('mcui-stonecutterArrow')
	if (args.arrow or '') ~= '' then
		arrow:css(
			'background-image',
			'{{FileUrl|' .. args.arrow .. ' (' .. args.Mod .. ').png}}'
		)
	end
		arrow:wikitext(addSlot(args, 'Output', '', 'invslot-plain invslot-noformat mcui-stonecutterSprite'))
	
	body
		:tag('span')
			:addClass('mcui-output')
			:wikitext(addSlot(args, 'Output', 'O', 'invslot-large'))
	
	return tostring(mw.html.create('div'):node(body))
end

-- Pre-1.20 Smithing Table
function p.legacySmithing(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	
	local body = mw.html.create('span'):addClass('mcui mcui-legacySmithing pixel-image')
	
	body:tag('span'):addClass('mcui-text'):wikitext('Upgrade Gear'):done()
	body:tag('span'):addClass('mcui-smithingHammer'):tag('br'):done()
	
	local bottom = body:tag('div'):addClass('mcui-bottom')
	
	local input = bottom:tag('span'):addClass('mcui-input')
	input:wikitext(addSlot(args, 'Input1', 'I1'))
    input:tag('span'):addClass('mcui-plus'):done()
	input:wikitext(addSlot(args, 'Input2', 'I2'))
	
	bottom:tag('span'):addClass('mcui-arrow'):tag('br'):done()
	
	bottom
		:tag('span')
			:addClass('mcui-output')
			:wikitext(addSlot(args, 'Output', 'O'))
	
	return tostring(mw.html.create('div'):node(body))
end

-- Post-1.20 Smithing Table
function p.smithingTable(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	
	local body = mw.html.create('span'):addClass('mcui mcui-smithingTable pixel-image')
	
	body:tag('span'):addClass('mcui-text'):wikitext('Upgrade Gear'):done()
	body:tag('span'):addClass('mcui-smithingHammer'):tag('br'):done()
	
	local bottom = body:tag('div'):addClass('mcui-bottom')
	
	local input = bottom:tag('span'):addClass('mcui-input')
	input:wikitext(addSlot(args, 'Input1', 'I1'))
	input:wikitext(addSlot(args, 'Input2', 'I2'))
	input:wikitext(addSlot(args, 'Input3', 'I3'))
	
	bottom:tag('span'):addClass('mcui-arrow'):tag('br'):done()
	
	bottom
		:tag('span')
			:addClass('mcui-output')
			:wikitext(addSlot(args, 'Output', 'O'))
	
	return tostring(mw.html.create('div'):node(body))
end

-- Loom
function p.loom(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	
	local body = mw.html.create('span'):addClass('mcui mcui-Loom pixel-image')
	
	local tapestry = body:tag('span'):addClass('mcui-tapestry')
	if args.Banner and #args.Banner>0 then
		tapestry:wikitext(addSlot(args, 'Banner', 'B', 'mcui-inputBanner'))
	end
	if args.Dye and #args.Dye>0 then
		tapestry:wikitext(addSlot(args, 'Dye', 'D', 'mcui-inputDye'))
	end
	if args.Pattern and #args.Pattern>0 then
		tapestry:wikitext(addSlot(args, 'Pattern', 'P', 'mcui-inputPattern'))
	end
	tapestry:tag('span'):tag('br'):done()
	local arrow = body:tag('span'):addClass('mcui-loomArrow')
	if args.arrow or '' ~= '' then
		arrow:css(
			'background-image',
			'{{FileUrl|' .. args.arrow .. ' (' .. args.Mod .. ').png}}'
		)
	end
	
	local sprite = args.Sprite
	local bannerSprite
	if sprite and #sprite>0 then
		local animate = require([[Module:AnimateSprite]]).animate
		bannerSprite = animate{
			args.Sprite,
			sheet = 'SlotSprite'
		}
	else
		bannerSprite = '<br>'
	end
	
	arrow
		:tag('span')
		:addClass('mcui-bannerSprite')
		:wikitext(bannerSprite)
	
	body
		:tag('span')
			:addClass('mcui-output')
			:wikitext(addSlot(args, 'Output', 'O', 'invslot-large'))
	
	return tostring(mw.html.create('div'):node(body))
end

-- Grindstone
function p.grindstone(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	
	local body = mw.html.create('span'):addClass('mcui mcui-Grindstone pixel-image')
	
	local grindstone = body:tag('span'):addClass('mcui-grindstone')
		grindstone:wikitext(addSlot(args, 'Input1', 'I1', 'mcui-input1'))
		grindstone:wikitext(addSlot(args, 'Input2', 'I2', 'mcui-input2'))
	local arrow = body:tag('span'):addClass('mcui-arrow')
	if args.arrow or '' ~= '' then
		arrow:css(
			'background-image',
			'{{FileUrl|' .. args.arrow .. ' (' .. args.Mod .. ').png}}'
		)
	end
	
	body
		:tag('span')
			:addClass('mcui-output')
			:wikitext(addSlot(args, 'Output', 'O', 'invslot-large'))
	
	return tostring(mw.html.create('div'):node(body))
end
-- Crushing Wheel
function p.crushingWheel(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		manyInputs=false,
		manyOutputs=true,
		allowChance=true,
		slot='Crushing',
		paddingtop = '14px',
		paddingtop2 = '14px'
	}
end

--Bulk Washing
function p.bulkWashing(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		manyInputs=false,
		manyOutputs=true,
		allowChance=true,
		slot='Bulk Washing',
		paddingtop = '14px',
		paddingtop2 = '14px'
	}
end
--Bulk Haunting
function p.bulkHaunting(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		manyInputs=false,
		manyOutputs=true,
		allowChance=true,
		slot='Bulk Haunting',
		paddingtop = '14px'
	}
end
--Bulk Smoking
function p.bulkSmoking(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		manyInputs=false,
		manyOutputs=false,
		allowChance=false,
		slot='Bulk Smoking',
		paddingtop = '14px'
	}
end
--Bulk Blasting
function p.bulkBlasting(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		manyInputs=false,
		manyOutputs=false,
		allowChance=false,
		slot='Bulk Blasting',
		paddingtop = '14px'
	}
end
--Deploying
function p.deploying(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		manyInputs=true,
		manyOutputs=false,
		allowChance=false,
		slot='Deploying',
		paddingtop = '14px'
	}
end
--Manual Item Application
function p.manualApplication(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		manyInputs=true,
		manyOutputs=false,
		allowChance=false,
		slot='Manual Item Application',
		paddingtop = '14px'
	}
end
--Mechanical Mixer
function p.mechanicalMixer(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	if args.type:lower() == 'crafting' or args.type:lower() == 'shapeless' then
		return p.commonMachine{
			args,
			manyInputs=true,
			manyOutputs=false,
			allowChance=false,
			slot='Mechanical Mixer Crafting',
			paddingtop = '14px'
		}
	elseif args.type:lower() == 'mixing' then
		return p.commonMachine{
			args,
			manyInputs=true,
			manyOutputs=false,
			allowChance=false,
			slot='Mechanical Mixer Mixing',
			lowerslot=args.Heating,
			paddingtop = args.Heating and '6px' or '14px',
			paddingbottom = '0'
		}
	elseif args.type:lower() == 'brewing' then
		return p.commonMachine{
			args,
			manyInputs=true,
			manyOutputs=false,
			allowChance=false,
			slot='Mechanical Mixer Brewing',
			lowerslot=args.Heating,
			paddingtop = args.Heating and '6px' or '14px',
			paddingbottom = '0'
		}
	else
		return '<strong><font color="red">Template error: invalid type specified</font></strong>'
	end
end
--Mechanical Press
function p.mechanicalPress(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	if args.type:lower() == 'crafting' or args.type:lower() == 'packing' then
		return p.commonMachine{
			args,
			inputType = 'grid',
			manyOutputs=false,
			allowChance=false,
			isOneItemType=true,
			slot='Mechanical Press Crafting',
			paddingtop = '10px',
			paddingbottom = '6px',
			paddingtop2 = '6px',
		}
	elseif args.type:lower() == 'compacting' then
		return p.commonMachine{
			args,
			manyInputs=true,
			manyOutputs=false,
			allowChance=false,
			slot='Mechanical Press Compacting',
			paddingtop = '14px',
		}
	elseif args.type:lower() == 'pressing' then
		return p.commonMachine{
			args,
			manyInputs=false,
			manyOutputs=false,
			allowChance=false,
			slot='Mechanical Press Pressing',
			paddingtop = '14px',
		}
	else
		return '<strong><font color="red">Template error: invalid type specified</font></strong>'
	end
end
-- Millstone
function p.millstone(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		manyInputs=false,
		manyOutputs=true,
		allowChance=true,
		slot='Milling',
		paddingtop = '14px',
		paddingtop2 = '20px'
	}
end
-- Mechanical Crafter
function p.mechanicalCrafter(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		inputType = 'mechanicalCrafter',
		manyInputs=false,
		manyOutputs=false,
		allowChance=false,
		slot='Mechanical Crafting',
		paddingbottom = '6px',
		largeOutputSlot = true,
	}
end
--Mechanical Saw
function p.mechanicalSaw(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		manyInputs=false,
		manyOutputs=true,
		allowChance=false,
		slot='Sawing',
		paddingtop = '14px'
	}
end
--Spout
function p.spout(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		manyInputs=true,
		manyOutputs=false,
		allowChance=false,
		slot='Filling by Spout',
		paddingtop = '14px'
	}
end
--Sandpaper
function p.sandpaper(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	return p.commonMachine{
		args,
		manyInputs=false,
		manyOutputs=false,
		allowChance=false,
		slot='Sandpaper Polishing;Sandpaper Polishing (Red)',
		paddingtop = '14px'
	}
end
-- Sequenced Assembly (WIP)
function p.sequencedAssembly(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
		local body = mw.html.create('span'):addClass('mcui mcui-Sequenced_Assembly pixel-image')
		local input = body:tag('span'):addClass('mcui-input')
		input:wikitext(addSlot(args, 'Input', 'I'))
		local Sequence = ''
		local Sequence1 = input:tag('span'):addClass('mcui-sequence1'):done()
		local Sequence2 = input:tag('span'):addClass('mcui-sequence2'):done()
		local Sequence3 input:tag('span'):addClass('mcui-sequence3'):done()
end
-- Common Machines
function p.commonMachine(options)
	local args = options[1]
	
	local body = mw.html.create('span'):addClass('mcui mcui-Common_Machines pixel-image')
	local input
	local i = 1
	local totalItems = 0
	local inputRows = 0
	local outputRows = 0
	if options.inputType == 'grid' or options.inputType == 'mechanicalCrafter' then
		input = body:tag('table'):addClass('mcui-input')
		if options.inputType == 'mechanicalCrafter' then
			for num = 1, 5 do
				local rowHasEntry = false
				for _, letter in ipairs{ 'A', 'B', 'C', 'D', 'E' } do
					if  args[letter..num] and mw.text.trim(args[letter..num]) ~= '' then 
						rowHasEntry = true
						break
					end
				end
				if rowHasEntry then
					inputRows = inputRows + 1
					local row = input:tag('tr'):addClass('mcui-row')
					for letternum, letter in ipairs{ 'A', 'B', 'C', 'D', 'E' } do
						if not args.gridwidth or letternum <= tonumber(args.gridwidth) then
						    local td = row:tag('td')
						    if args[letter..num] and mw.text.trim(args[letter..num]) ~= '' then
						    	td:wikitext(slot{args[letter..num]})
						    	totalItems = totalItems + 1
						    	isEmptyRow = false
						    else
						    	td:wikitext(slot{
						    		nil,
						    		class='invslot-noformat'
						    	})
						    end
						end
					end
				end
			end
			local paddingtops = {
				[0] = '0',
				[1] = '18px',
				[2] = '8px',
				[3] = '6px',
				[4] = '6px',
				[5] = '6px',
			}
			options.paddingtop = paddingtops[inputRows]
			
		elseif args.smallgrid then
			for num = 1, 2 do
				local row = input:tag('tr'):addClass('mcui-row')
				inputRows = inputRows + 1
				for _, letter in ipairs{ 'A', 'B' } do
				    local td = row:tag('td')
					local itemArg = options.isOneItemType and 'Input' or letter..num
					td:wikitext(slot{args[itemArg]})
				end
			end
		else
			for num = 1, 3 do
				local row = input:tag('tr'):addClass('mcui-row')
				inputRows = inputRows + 1
				for _, letter in ipairs{ 'A', 'B', 'C' } do
				    local td = row:tag('td')
					local itemArg = options.isOneItemType and 'Input' or letter..num
					td:wikitext(slot{args[itemArg]})
				end
			end
		end
	elseif options.inputType == 'normal' or not options.inputType then
		input = body
			:tag('table')
				:addClass('mcui-input')
				:tag('tr')
					:addClass('mcui-row')
		
		while args['Input'..i] or args['I'..i] or (i == 1 and (args['Input'] or args['I'])) do
			local iItem = options.manyInputs and (args['Input'..i] or args['I'..i]) or nil
			local item = i == 1 and (args['Input'] or args['I'] or iItem) or iItem
			input = addSlotElement(input, item)
			i = i + 1
		end
	end
	local middle = body
		:tag('div')
			:addClass('mcui-middle')
	middle:tag('div')
		:wikitext(slot{
			table.concat{
				options.slot, ',', totalItems,
				(totalItems > 0 and table.concat{'[&7Requires ', totalItems, ' Crafters!]'} or ''),
			},
			class = 'invslot-noformat'
		})
	:done()
	middle
		:tag('div')
		:addClass(options.arrowclass or 'mcui-arrow-long')
		:done()
	if options.lowerslot then
		middle:tag('div')
			:css{
				['position']='relative',
				['bottom']='8px',
			}
			:wikitext(slot{
				options.lowerslot,
				class = 'invslot-noformat'
			})
		:done()
	end
	
	local output = body
		:tag('table')
			:addClass('mcui-output')
	
	local isChance = false
	if options.allowChance == nil then options.allowChance = true end
	if options.allowChance then
		for j=1,50,1 do
			if args['Chance'..j] or args['C'..j] then
				isChance = true
				break
			end
		end
	end
	if isChance then 
		output:css{['top']='9px'}
		body:css{['padding-bottom']='9px'}
	end
	
	i = 1
	local rows = {}
	local j = 1
	while args['Output'..i] or args['O'..i] or (i == 1 and (args['Output'] or args['O'])) do
		if i % 5 == 1 then 
			rows[j] = output:tag('tr'):addClass('mcui-row')
			outputRows = outputRows + 1
		end
		local iItem = options.manyOutputs and (args['Output'..i] or args['O'..i]) or nil
		local item = i == 1 and (args['Output'] or args['O'] or iItem) or iItem
		local chance = i == 1 and (args['Chance'] or args['C'] or args['Chance'..i] or args['C'..i]) or (args['Chance'..i] or args['C'..i])
		rows[j] = addSlotElement(rows[j], item, chance, isChance and options.allowChance, options.largeOutputSlot)
		i = i + 1
		if i % 5 == 1 then j = j + 1 end
	end
	if isChance then
		if options.paddingbottom then
			body:css{
				['padding-top'] = options.paddingtop2 or '20px',
				['padding-bottom'] = options.paddingbottom or '0'
			}
		else
			body:css{['padding-top'] = options.paddingtop2 or '20px'}
		end
	else
		if options.paddingbottom then
			body:css{
				['padding-top'] = options.paddingtop or '14px',
				['padding-bottom'] = options.paddingbottom or '0'
			}
		else
			body:css{['padding-top'] = options.paddingtop or '14px'}
		end
	end
	
	if options.lowerslot then
		middle:css{['bottom']='0'}
	else
		local bottoms = {
			[0] = '11px',
			[1] = '12px',
			[2] = '5px',
			[3] = '-14px',
			[4] = '-31px',
			[5] = '-48px',
		}
		middle:css{['bottom']=bottoms[inputRows > outputRows and inputRows or outputRows] or options.bottom}
	end
	
	return tostring(mw.html.create('div'):node(body))
end
function addSlotElement(element, item, chance, allowChance, largeOutputSlot)
	if allowChance then
		element
			:css{['top']='9px'}
			:tag('td')
				:tag('span')
					:wikitext(slot{item})
				:done()
				:tag('span')
					:addClass(chance and 'mcui-text' or 'mcui-text mcui-text-nondisplay')
					:wikitext(chance or 'nil')
				:done()	
			:done()
		:done()
	else
		element
			:tag('td')
				:wikitext(slot{item, class=largeOutputSlot and 'invslot-large' or nil})
			:done()
		:done()
	end
	return element
end

function p.slotList(f)
	local args = f
	if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
	local maxWidth = tonumber(args.maxwidth or args.width or args.w) or 6
	
	local wikitable = mw.html.create('table')
			:addClass('mcui-output') 
	
	local i = 1
	while args[i] and mw.text.trim(args[i]) ~= '' do
		local row = wikitable:tag('tr'):addClass('mcui-row')
		local j = 1
		while args[i] and mw.text.trim(args[i]) ~= '' and j <= maxWidth do
			row:tag('td'):wikitext(slot{args[i], class='invslot-noformat'}):done()
			i = i + 1
			j = j + 1
		end
	end
	return tostring(wikitable)
end
return p