The Gamepedia and Fandom account systems have now been merged. If your username is incorrect, you have accounts on both platforms that weren't merged, or you have trouble signing in, please submit a support ticket.

Module:UI

From Minecraft Wiki
Jump to: navigation, search
[view | edit | history | purge]DocumentationJump to code ↴

This module implements common UI templates, to avoid overhead from excessive #invoke calls.

Dependencies

See also

[view | edit | history | purge]The above documentation is transcluded from Module:UI/doc.
local slot = require( [[Module:Inventory slot]] ).slot
local addSlot = function( 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
	}
end

function experience_image(exp_value)

	local MINMAX = {
	  {-32768, 2},
	  {3, 6},
	  {7, 16},
	  {17, 36},
	  {37, 72},
	  {73, 148},
	  {149, 306},
	  {307, 616},
	  {617, 1236},
	  {1237, 2476},
	  {2477, 32767}
	}

	local EXP_IMGS = {
		"Experience Orb Value -32768-2.png",
		"Experience Orb Value 3-6.png",
		"Experience Orb Value 7-16.png",
		"Experience Orb Value 17-36.png",
		"Experience Orb Value 37-72.png",
		"Experience Orb Value 73-148.png",
		"Experience Orb Value 149-306.png",
		"Experience Orb Value 307-616.png",
		"Experience Orb Value 617-1236.png",
		"Experience Orb Value 1237-2476.png",
		"Experience Orb Value 2477-32767.png",
	}
	
	local n = assert( tonumber(exp_value), "Module:UI: Experience value is not a number (" .. exp_value .. ")" )
	
	local idx = 2; exp = tonumber( exp_value )
	if exp <= MINMAX[#MINMAX][2] then
	  for i = 1, #MINMAX do
		if MINMAX[i][1] < exp and MINMAX[i][2] >= exp then
		  idx = i
		  break
		end
	  end
	end
	
	return tostring( EXP_IMGS[idx] )
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' )
	
	local input = body:tag( 'span' ):addClass( 'mcui-input' )
	for num = 1, 3 do
		local row = input:tag( 'span' ):addClass( 'mcui-row' )
		for _, letter in ipairs{ 'A', 'B', 'C' } do
			row: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' ) )
			
	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 ) )
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 mcui-stonecutterSprite' ) )
	
	body
		:tag( 'span' )
			:addClass( 'mcui-output' )
			:wikitext( addSlot( args, 'Output', 'O', 'invslot-large' ) )
	
	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
-- Smithing Table
function p.smithing (f) 
local args = f
if f == mw.getCurrentFrame() then
		args = f:getParent().args
	else
		f = mw.getCurrentFrame()
	end
return tostring( mw.html.create( 'div' ):node( body ) )
end
return p