Module:UI

-- -- Taken from: https://minecraft.gamepedia.com/Module:UI local multiRequire = require('Module:MultiRequire').multiRequire local getArgs = require('Module:Arguments').getArgs local slot = require(Module:Inventory slot).slot local tooltips = mw.loadData('Module:Inventory slot/Aliases') local parseFrameText = require(Module:Inventory slot).parseFrameText local rarityAliases = require('Module:RarityTier/Aliases') local table, string, lu, uiText, uiColors, yesno = multiRequire('Module:Table', 'Module:String', 'Module:LibraryUtil', 'Module:UIText', 'Module:UIText/Data', 'Module:Yesno')

local formatUIText = uiText._main local titleObj = mw.title.getCurrentTitle

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, 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 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',			''		) 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',			''		) 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',			''		) 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',			''		) 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',			''		) 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 = ' ' 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',			''		) end body :tag('span') :addClass('mcui-output') :wikitext(addSlot(args, 'Output', 'O', 'invslot-large')) return tostring(mw.html.create('div'):node(body)) end

-- Melody function p.noteSequence(f) local args = getArgs(f) local sequence = args[1] return p._noteSequence(sequence) end

function p._noteSequence(sequence) local function simpleSlot(frames) frames = parseFrameText(frames, nil, false, {aliases = '', default = nil}) local function simpleMakeItem(name) return mw.html.create('span'):addClass('invslot-item invslot-item-image'):wikitext(''):done end local body = mw.html.create('span'):addClass('invslot animated') local activeFrame = 1 for i, frame in ipairs(frames) do           local item if frame[1] then item = body:tag('span'):addClass('animated-subframe') local subActiveFrame = 1 --FC-frame.randomise and random(#frame) or 1 for sI, sFrame in ipairs(frame) do                   local sItem = simpleMakeItem(sFrame.name) item:node(sItem) if sI == subActiveFrame then sItem:addClass('animated-active') else sItem:addClass('hidden') end end else item = simpleMakeItem(frame.name) body:node(item) end if i == activeFrame and animated then item:addClass('animated-active') elseif animated then item:addClass('hidden') end end return mw.getCurrentFrame:preprocess(tostring(body)) end

local colors = { "Red", "Yellow", "Lime", "Green", "Purple", "Blue", "Light_Blue" }

local slots = {} for x = 1,7,1 do       slots[x] = {} for y = 1,6,1 do          if y == 5 then slots[x][y] = sequence:gsub('['..x..']', 'Block_of_Quartz;') else slots[x][y] = sequence:gsub('['..x..']', colors[x]..'_Wool;') end if y == 5 then slots[x][y] = slots[x][y]:gsub('[%d%s]', colors[x]..'_Stained_Clay;') else slots[x][y] = slots[x][y]:gsub('[%d%s]', colors[x]..'_Stained_Glass_Pane;') end if y == 5 then for z = 1,y,1 do                      slots[x][y] = colors[x]..'_Stained_Clay;'..slots[x][y] end for z = 1,12-y,1 do                      slots[x][y] = slots[x][y]..colors[x]..'_Stained_Clay;' end else for z = 1,y,1 do                      slots[x][y] = colors[x]..'_Stained_Glass_Pane;'..slots[x][y] end for z = 1,12-y,1 do                      slots[x][y] = slots[x][y]..colors[x]..'_Stained_Glass_Pane;' end end slots[x][y] = slots[x][y]:gsub('[_]', ' ') end end

local table = mw.html.create('table'):addClass('mcui mcui-Crafting_Table pixel-image'):css({margin='0 auto', display='table', cursor='not-allowed'})

for y = 1,6,1 do       local row = table:tag("tr"):addClass('mcui-row') row:tag("td"):wikitext(simpleSlot('Gray Stained Glass Pane')):done for x = 1,7,1 do           row:tag("td"):wikitext(simpleSlot(slots[x][y])):done end row:tag("td"):wikitext(simpleSlot('Gray Stained Glass Pane')):done row:done end table:done return tostring(table) end

- -- function: createBlankUI(topText: string, id?: string, goBack?: table, hide?: boolean, fill?: boolean, rows?: number, cols?: number) -- -- Creates a new Blank UI. - local function createBlankUI(topText, id, goBack, hide, fill, rows, cols) local Methods = {} local goBack = goBack or {} local rows = tonumber(rows) or 6 local cols = tonumber(cols) or 9 -	-- function: createBlankUI:constructor -- 	-- Constructor function for the methods provided. Creates the actual UI. -	function Methods:constructor self.slots = {} self.custom = {} self.wt = mw.html.create('table') :attr{ class="mcui mcui-Crafting_Table pixel-image" } :css{ ['margin'] = '0 auto'; ['display'] = 'table'; }			:tag('tr') :css{ ['position'] = 'absolute'; ['margin-top'] = '-4px'; }				:tag('td') :attr{ colspan=9 } :css{ ['font-family'] = 'minecraft'; ['color'] = '#2B2D2F'; ['font-size'] = '14px'; }					:wikitext(topText) :done :done for x = 1, rows, 1 do			self.slots[x] = {} self.custom[x] = {} for y = 1, cols, 1 do				if x == rows and y == 4 then self:setSlot(x, y, { 						'Go Back', 						text=goBack.text and '&7To '..goBack.text,						link=goBack.link or 'none',						title='&aGo Back',						class=goBack.id and 'goto-'..goBack.id:gsub('^goto%-', ''),					}) elseif x == rows and y == 5 then self:setSlot(x, y, { 'Close' }) else if not yesno(fill, true) then self:setEmptySlot(x, y)					else self:setBlankSlot(x, y)					end end end end end -	-- function: createBlankUI:setSlot(x: number, y: number, args: table, isCustom?: boolean) -- 	-- Sets a slot according to the `x` and `y` parameters provided, with the arguments -- to the parser as `args`. -	function Methods:setSlot(x, y, args, isCustom) checkType(1, x, 'number') checkType(2, y, 'number') checkType(3, args, { 'table', 'string' })

local tp = type(args) if tp == 'table' or (tp == 'string' and args:match('.-')) then self.slots[x] = self.slots[x] or {} self.custom[x] = self.custom[x] or {} self.slots[x][y] = args self.custom[x][y] = not not isCustom elseif tp == 'string' then assertTrue(self.slots[x] and self.slots[x][y], 'slot in posistion (%d, %d) does not exist', 2, x, y)[args] = isCustom end return self end

-	-- function: createBlankUI:getSlot(x: number, y: number, prop?: string) -- 	-- Gets a slot according to the `x` and `y` parameters provided, with an option parameter -- of `prop` to get a particular slot property. -	function Methods:getSlot(x, y, prop) if prop then return assertTrue(self.slots[x] and self.slots[x][y], 'slot in posistion (%d, %d) does not exist', 2, x, y)[prop] else return self.slots[x][y] end end -	-- function: createBlankUI:hasSlot(x: number, y: number) -- 	-- Checks if the UI has a specific slot based on `x` and `y`. -	function Methods:hasSlot(x, y)		return not not self.slots[x][y] end -	-- function: createBlankUI:isEmptySlot(x: number, y: number) -- 	-- Checks if a slot based on `x` and `y` is not blank. -	function Methods:isEmptySlot(x, y)		return self.slots[x][y] and self.slots[x][y] ~= '' and self.slots[x][y] ~= "Blank" end -	-- function: createBlankUI:setBlankSlot(x: number, y: number) -- 	-- Sets a blank slot according to the `x` and `y` parameters provided. -	function Methods:setBlankSlot(x, y)		return self:setSlot(x, y, { 'Blank' }) end -	-- function: createBlankUI:setEmptySlot(x: number, y: number) -- 	-- Sets a empty slot according to the `x` and `y` parameters provided. -	function Methods:setEmptySlot(x, y)		return self:setSlot(x, y, { "" }) end -	-- function: createBlankUI:__tostring -- 	-- __tostring metamethod for the class. Parses the `slots` to an acual string. -	function Methods:__tostring for x, xValue in ipairs(self.slots) do			local row = self.wt:tag('tr') :addClass('mcui-row') :css{ ['margin-top'] = x == 1 and '24px' or nil }			for y, yValue in ipairs(xValue) do				row:tag('td') :wikitext(self.custom[x][y] and yValue or slot(yValue)) :done end row:done end

return id			and tostring(mw.html.create('div')				:node(self.wt)				:attr{ 					id=id and 'ui-'..id:gsub('^ui%-', ''), 					class=id and "sbw-ui-tab-content", 					style=(titleObj.namespace == 0 and yesno(hide)) and "display: none;" or nil,				} 			:done) or tostring(self.wt) end

return table.makeClass(Methods) end p.createBlankUI = createBlankUI

- -- Template: Collection UI -- -- Creates a main collection UI for a given item - function p.collectionUI(frame) return p._collectionUI(table.deepCopy(getArgs(frame))) end

- -- _collectionUI Helper functions - local rarityReplace = mw.clone(rarityAliases)

local recipeAliases = { ['r'] = 'recipe', ['recipe'] = 'recipe', ['recipes'] = 'recipes', ['rs'] = 'recipes', ['rec'] = 'recipe', ['recs'] = 'recipes', ['recip'] = 'recipe', ['recips'] = 'recipes', ['res'] = 'recipes', ['re'] = 'recipe', ['up'] = 'upgrade', ['upg'] = 'upgrade', ['u'] = 'upgrade', ['upgr'] = 'upgrade', ['upgra'] = 'upgrade', ['upgrad'] = 'upgrade', ['upgrade'] = 'upgrade', }

for k, v in pairs(rarityReplace) do	rarityReplace[k] = '' end

local function replaceRarity(s) return s and s:gsub(s, rarityReplace) end

local function specialCaseColors(s) local matches = { ['[Mm]inion'] = 'blue', ['[Uu]pgrade'] = 'green', ['[Cc]oming [Ss]oon'] = 'red', }

for k, v in pairs(matches) do		if s:match(k) then return uiColors.conversions[v] end end if tonumber(s) then return uiColors.conversions['dark_aqua'] end end

local function isUpgrade(s) return not not s:match('[Uu]pgrade') end

local function isComingSoon(t) return not not t:match('[Cc][Oo][Mm][Ii][Nn][Gg] [Ss][Oo][Oo][Nn]') end

local function isExperience(t) return not not t:match('[Ee]xperience') end

local function isNone(t) return not not t:match('[Nn]one') or not not t:match('[Uu]pgrade') end

local function parseCollectionData(ui, rewards, collection) local rows = 1 local firstRowPositions = { { {5, 3} },		{ {4, 3}, {6, 3} },		{ {4, 3}, {5, 3}, {6, 3} },		{ {3, 3}, {4, 3}, {6, 3}, {7, 3} },		{ {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3} },		{ {2, 3}, {3, 3}, {4, 3}, {6, 3}, {7, 3}, {8, 3} },		{ {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}, {8, 3} },	}

for total, v in ipairs(rewards) do		local x		local y		if total > 21 then break; end

if total <= 7 then local index = #rewards>7 and 7 or #rewards local pos = firstRowPositions[index][total] x, y = pos[2], pos[1] else x = 3+rows-1 y = total%7 y = y == 0 and 7+1 or y+1 end if total%7 == 0 and total/7 >= 1 then rows = rows+1 end ui:setSlot(x, y, {			total == 1 and "Yellow Stained Glass Pane,"..total or 'Red Stained Glass Pane,'..total,			link='none',			title=table.concat{ '&e', collection, ' ', string._toRoman(total) },			class=v._goto and 'goto-'..v._goto,			text=formatUIText(string.dedent			\n&7Progress: &e0&6%%			&f%s &e0&6\\/&e%s&7			%s:			%s			&eClick to view rewards!			):format( ('-'):rep(20), string._formatShortNum(string._toNumber(v.amount)), #v > 1 and '&7Rewards' or '&7Reward', table.concat(table.map(v, function(val) local s = val[1] local isExperience = val.type and isExperience(val.type) or false local isComingSoon = val.type and isComingSoon(val.type) or false local isNone = val.type and isNone(val.type) or false isNone = isNone or isUpgrade(s) return table.concat{ isExperience and '&8+' or '', val.rarity..s, 						isNone and ' ' or ' &r', isNone and '' or (isComingSoon and '&8(&4COMING SOON&8)' or (val.type or (s:match('[Mm]inion') and 'Recipes'or 'Recipe'))), }				end), '/') )		})	end end

local function parseTextList(s) local rewards = {} local count = 0 for i, v in ipairs(string.split((s:gsub('\\,', '\255')), '\n')) do		local _type v = string.methods(v):_trim if v:getValue ~= '' then if v:charAt(1) == "*" then if v:charAt(2) == "*" then _type = 'item' else _type = 'amount' end end if _type == 'amount' then local amount, _goto = unpack(string.split(v:sub(2), "%s*,%s*")) count = count+1 rewards[count] = {} rewards[count].amount = amount rewards[count]._goto = _goto and _goto:gsub('^goto%-', '') elseif _type == 'item' then local item, type, rarity = unpack(string.split(v:sub(3), '%s*,%s*')) item = item or v:sub(3) rarity = (rarity and rarity ~= "") and uiText.getRarityColor(rarity) local tooltip = tooltips[item] local split = string.split(tooltip and tooltip.text or '', '[\n\\]') local tooltipRarity = split[#split > 1 and #split-1 or 1] tooltipRarity = tooltipRarity and (tooltipRarity:match('^&([a-z0-9])&l') or tooltipRarity:match('&([a-z0-9])&l%w*$'))

table.push(rewards[count], { 					item, 					rarity = '&'..(tooltipRarity or rarity or specialCaseColors(item) or 'f'),					type=(type and type ~= "") and string.ucfirst(recipeAliases[type:lower] or type)				}) end end end return rewards end - -- function: _collectionUI(args: table|frame) -- -- Invoked by. - function p._collectionUI(args) checkType(1, args, { 'table' }) assertTrue(args[1], 'No collection specified', 2) assertTrue(args[2], 'No collection rewards specified', 2) local slots = {} local collection = args[1] and args[1]:gsub('[Ee][Nn][Cc][Hh][Aa]?[Nn]?[Tt]?[Ee]?[Dd]? ?', ):gsub('[Bb][Ll][Oo][Cc][Kk] ?[Oo]?[Ff]? ?', ) local title = mw.title.getCurrentTitle local ui = createBlankUI(collection and collection..' Collection' or title.rootText, args['id'], { 		text=(args['return_text'] or args['goback']),		link=(args['return_text'] or args['goback']) and (args['return_text'] or args['goback']):gsub('%s*[Cc]ollection', ''),		id=args['return_id'],	}, args['hide'])

ui:setSlot(1, 5, {		args.title or collection,		link='none', 		title='&a'..collection..' Collection',		text=formatUIText(string.dedent		&7View all your %s Collection 		&7progress and rewards!		&7Total Collected: &e0		:format(collection))	}) ui:setSlot(6, 4, 'link', '') parseCollectionData(ui, parseTextList(args[2]), collection) -- pipeline(ui, table.dump, 0, error)

return (tostring(ui):gsub('\\(.)', '%1'):gsub('\255', ',')) end

- -- Template: Collection Rewards UI -- -- Creates a collection Rewards UI. - function p.collectionRewardsUI(frame) local args = getArgs(frame)

return p._collectionRewardsUI(table.deepCopy(args)) end - -- function: _collectionRewardsUI(args) -- -- Invoked by - function p._collectionRewardsUI(args) checkType(1, args, { 'table' }) local collection = args[1] and args[1]:gsub('[Ee][Nn][Cc][Hh][Aa]?[Nn]?[Tt]?[Ee]?[Dd]? ?', ):gsub('[Bb][Ll][Oo][Cc][Kk] ?[Oo]?[Ff]? ?', ) local ui = createBlankUI(collection..' '..string._toRoman(args[2] or 1)..' Rewards', args['id'], {		text=collection..' Collection',		link=args['return_text'] and args['return_text']:gsub('%s*[Cc]ollection', ''),		id=args['return_id'],	}, args['hide'])

local rewards = {} local items = table.filter(string.split(args[3], '\n'), function(v)		return string.trim(v) ~= ''	end) local amount = #items local posistions = { { {3, 5} },		{ {3, 4}, {3, 6} },		{ {3, 3}, {3, 5}, {3, 7} },		{ {3, 2}, {3, 4}, {3, 6}, {3, 8} },		{ 			{2, 2}, {2, 4}, {2, 6}, {2, 8},			{4, 5},		},		{ 			{2, 2}, {2, 4}, {2, 6}, {2, 8},			{5, 4}, {5, 6},		},		{ 			{2, 2}, {2, 4}, {2, 6}, {2, 8},			{3, 3}, {3, 5}, {3, 7},		},		{ 			{2, 2}, {2, 4}, {2, 6}, {2, 8},			{4, 2}, {4, 4}, {4, 6}, {4, 8},		},		{ 			{2, 4}, {2, 5}, {2, 6},			{3, 4}, {3, 5}, {3, 6},			{4, 4}, {4, 5}, {4, 6},		},		{ 			{2, 4}, {2, 5}, {2, 6}, {2, 7},			{3, 4}, {3, 5}, {3, 6},			{4, 4}, {4, 5}, {4, 6},		},		{ 			{2, 3}, {2, 4}, {2, 5}, {2, 6}, {2, 7},			{3, 4}, {3, 5}, {3, 6},			{4, 4}, {4, 5}, {4, 6},		},	}	for i, line in ipairs(items) do		local item, id, title, desc = pipeline(line, string.trim, 2, string.sub, '%s*,%s*', string.unpackedSplit) local tooltip = tooltips[item] local itemText = desc or (tooltip and tooltip.text) local itemTitle = title or (tooltip and tooltip.title) local function addItem(x, y)			ui:setSlot(x, y, {				item, text=itemText and itemText..'//&eClick to view recipe!', 				title=itemTitle, class=id and 'goto-'..id:gsub('^goto%-', '')			}) end addItem(unpack(posistions[amount][i])) end return tostring(ui) end

- -- Template: UI -- -- Creates a UI. - function p.ui(frame) local args = getArgs(frame, { removeBlanks=false }) local ui = createBlankUI(args[1], args['id'], {		text=(args['return_text'] or args['goback']),		link=args['goback_link'],		id=args['return_id'],	}, args['hide'], args['fill'], args['rows'], args['cols']) local x = 1 local rowCount = 1 local maxRows, maxCols = tonumber(args['rows']) or 6, tonumber(args['cols']) or 9 local y = 1 local fill = yesno(args['fill'], nil) if fill == false then fill = nil end local function decodeCommas(...) local t = { ... }		for i, v in ipairs(t) do			t[i] = t[i]:gsub('\255', ',') end return unpack(t) end

local function setSlot(v, x, y)		local isCustom = v:match('<%a-(.-)>(.-)') v = v:gsub('\\,', '\255') local val, id, title, text = decodeCommas(string.unpackedSplit(v, '%s*,%s*')) if id == "" then id = nil end local _val = val local val, num = val:match('^%s*(.+)%s*[%-;]%s*(%d+)%s*$') val = val or _val ui:setSlot(x, y, isCustom and v or { 			val..(num and ', '..num or ), 			class=id and 'goto-'..id:gsub('^goto%-', ), 			title=title, 			text=text, 			link=id and (id == 'none' and 'none' or 'none'),		}, isCustom) end for i, v in ipairs(args) do		if i > 1 then if x > 6 then break; end if v:match('^%-$') then for y2 = y, maxCols do					if fill then ui:setSlot(x, y2, '') else ui:setBlankSlot(x, y2) end end x = x+1 y = 1 elseif y > maxCols then y = 1 x = x+1 else setSlot(v, x, y)				y = y+1 end end end

if yesno(args['noarrow'], false) and ui:isEmptySlot(maxRows, 4) then ui:setSlot(maxRows, 4, { not yesno(fill, true) and '' or 'Blank' }) end if yesno(args['noclose'], false) and ui:isEmptySlot(maxRows, 5) then ui:setSlot(maxRows, 5, { not yesno(fill, true) and '' or 'Blank' }) end for k, v in pairs(args) do		local k = tostring(k) if k:match('^%d%s*,%s*%d$') then local x, y = k:match('^(%d)%s*,%s*(%d)$') setSlot(v, tonumber(x), tonumber(y)) elseif k:match('^row%s*([1-6])%s*$') then local x = k:match('^row%s*([1-6])$') local endParams = v:match('%s*;%s*([%d%s,]-)%s*$') v = v:gsub('%s*;%s*([%d%s,]-)%s*$', '') local start, endNum if endParams then start, endNum = string.unpackedSplit(endParams, '%s*,%s*') end for y = tonumber(start) or 1, tonumber(endNum) or maxCols, 1 do				setSlot(v:gsub('%$n', y):gsub('\\%$n', '$n'), tonumber(x), y) end elseif k:match('^colu?m?n?%s*([1-9])%s*$') then local y = k:match('^colu?m?n?%s*([1-9])%s*$') local endParams = v:match('%s*;%s*([%d%s,]-)%s*$') v = v:gsub('%s*;%s*([%d%s,]-)%s*$', '') if endParams then start, endNum = string.unpackedSplit(endParams, '%s*,%s*') end for x = tonumber(start) or 1, tonumber(endNum) or maxRows, 1 do				setSlot(v:gsub('%$n', y):gsub('\\%$n', '$n'), x, tonumber(y)) end end end return tostring(ui) end p.slot = slot

- -- Template: Minion Recipes UI -- -- Creates a minion recipes UI - function p.minionRecipesUI(frame) return p._minionRecipesUI(table.deepCopy(getArgs(frame))) end

- -- function: minionRewardsUI(args: table|frame) -- -- Invoked by. - function p._minionRecipesUI(args) checkType(1, args, 'table') local col = (args[1] or titleObj.rootText):gsub('%s[Mm]inion', '') return p._collectionRewardsUI{ col, args[2] or 1, pipeline(		*%s Minion $n	, string.dedent, col, string.format, 11, string._repeat):gsub('(%d+)', function(m) return string._toRoman(m) end), hide=args['hide'], id=args['id'], return_id=args['return_id'], return_text=args['return_text'], } end

function p.forgingTable(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-Forging_Table pixel-image') -- CUSTOM: changing grid to use since wikia mobile doesn't support CSS local input = body:tag('table'):addClass('mcui-input') local row = input:tag('tr'):addClass('mcui-row') for num = 1, 6 do		if args[num] then local td = row:tag('td') td:wikitext(addSlot(args, num, 'I')) end end local arrow = body:tag('span'):addClass('mcui-arrow') :tag('span'):addClass('mcui-text mcui-overarrow-text'):wikitext(args.Time):done :tag('br') :done if args.arrow or  ~=  then arrow:css({			['background-image']='',			['margin-top']='0px'		}) end body :tag('span') :addClass('mcui-output') :wikitext(addSlot(args, 'Output', 'O', 'invslot-large')) return tostring(mw.html.create('div'):node(body)) end p.slot = slot

return p