Module:UI/Core

local loader = require('Module:Loader')

local makeClass, yesno, inventorySlot, random = loader.require('Class', 'Yesno', 'Inventory slot', 'Random') local colorData = loader.loadData('Color/Data') local slot = inventorySlot.slot

local backslashSubstitute = function(s) -- substitute every '\ ' but those that have special meaning for tooltips generation, e.g. '\&' s = s:gsub('\\\\', '\254'):gsub('\\([^&/])', '%1'):gsub('\254', '\\\\') return s end local backslashSubstituteStrict = function (s) -- substitute all '\ ' s = s:gsub('\\\\', '\254'):gsub('\\(.)', '%1'):gsub('\254', '\\\\') return s end

- -- function: createBlankUI(topText: string, id?: string, goBack?: table, hide?: boolean, fill?: boolean, rows?: number, cols?: number) -- -- Creates a new Blank UI. - local Interface = makeClass('Interface', {	aprilFools = false,	-	-- constructor(topText: string, id?: string, goBack?: table, hide?: boolean, fill?: boolean, rows?: number, cols?: number)	-- 	-- Constructor function for the methods provided. Creates the actual UI.	-	constructor = function (self, topText, id, goBack, hide, fill, rows, cols, noarrow, noclose, arrow_, close_)		goBack = goBack or {}		rows, cols = tonumber(rows) or 6, tonumber(cols) or 9		fill, noarrow, noclose = yesno(fill, true), yesno(noarrow, false), yesno(noclose, false)		local arrowX, arrowY, closeX, closeY		self.hide = hide		self.randomColor = colorData.MCColors[random.number{16}] -- for april fools only		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'] = '-8px', }				:tag('td') :attr{ colspan = cols, class = 'noselect', ['data-font-size'] = 14 } :css{ ['font-family'] = 'minecraft', ['color'] = '#2B2D2F', ['font-size'] = '14px', ['letter-spacing'] = '.2px', }					:wikitext(backslashSubstituteStrict(topText)) :done :done if arrow_ then if yesno(arrow_) or arrow_:match('[Nn]one') then noarrow = true else if arrow_:match('^%d+%s*,%s*%d+$') then arrowX, arrowY = arrow_:match('^(%d+)%s*,%s*(%d+)$') end end end arrowX = tonumber(arrowX) or rows arrowY = tonumber(arrowY) or 4 if close_ then if yesno(close_) or close_:match('[Nn]one') then noclose = true else if close_:match('^%d+%s*,%s*%d+$') then closeX, closeY = close_:match('^(%d+)%s*,%s*(%d+)$') end end end closeX = tonumber(closeX) or rows closeY = tonumber(closeY) or 5 for x = 1, rows, 1 do			self.slots[x] = {} self.custom[x] = {} for y = 1, cols, 1 do				if not noarrow and x == arrowX and y == arrowY then self:setSlot(x, y, {						'Go Back',						text=goBack.text,						link=goBack.link or 'none',						title='&aGo Back',						class=goBack.id and 'goto-'..goBack.id:gsub('^goto%-', ''),					}) elseif not noclose and x == closeX and y == closeY then self:setSlot(x, y, { 'Close' }) else if not fill then self:setEmptySlot(x, y)					else self:setBlankSlot(x, y)					end end end end end, -	-- 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`. -	setSlot = function (self, 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, -	-- 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. -	getSlot = function (self, 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, -	-- hasSlot(x: number, y: number) -- 	-- Checks if the UI has a specific slot based on `x` and `y`. -	hasSlot = function (self, x, y)		return not not self.slots[x][y] end, -	-- isEmptySlot(x: number, y: number) -- 	-- Checks if a slot based on `x` and `y` is not blank. -	isEmptySlot = function (x, y)		return self.slots[x][y] and self.slots[x][y] ~= '' and self.slots[x][y] ~= 'Blank' end, -	-- setBlankSlot(x: number, y: number) -- 	-- Sets a blank slot according to the `x` and `y` parameters provided. -	setBlankSlot = function (self, x, y)		if self.aprilFools then return self:setSlot(x, y, { ('Blank (%s)'):format(self.randomColor) }) end return self:setSlot(x, y, { 'Blank' }) end, -	-- setEmptySlot(x: number, y: number) -- 	-- Sets a empty slot according to the `x` and `y` parameters provided. -	setEmptySlot = function (self, x, y)		return self:setSlot(x, y, { '' }) end, -	-- __tostring -- 	-- __tostring metamethod for the class. Parses the `slots` to an acual string. -	__tostring = function (self) 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(backslashSubstitute(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 = yesno(self.hide) and 'display: none;' or nil,				} 			:done) or tostring(self.wt) end, static = { backslashSubstitute = backslashSubstitute, backslashSubstituteStrict = backslashSubstituteStrict, } })

return Interface