Module:Inventory slot: Difference between revisions

From Create: Minecraft Mod Wiki
Jump to navigation Jump to search
BoxWithout (talk | contribs)
m 3 revisions imported
BoxWithout (talk | contribs)
Replaced bad interwiki practices with better interwiki practices
 
Line 171: Line 171:
-- as plain text, but MediaWiki doesn't
-- as plain text, but MediaWiki doesn't
local escapedTitle = ( plainTitle or '' ):gsub( '&', '&' )
local escapedTitle = ( plainTitle or '' ):gsub( '&', '&' )
local escapedTitle = escapedTitle:gsub( 'w:c:minecraft:', 'Minecraft Wiki: ' )
local escapedTitle = escapedTitle:gsub( 'minecraft:', 'Minecraft Wiki: ' )
item:addClass( 'invslot-item-image' )
item:addClass( 'invslot-item-image' )
:wikitext( '[[File:', img, '|32x32px|link=', link or '', '|', escapedTitle, ']]' )
:wikitext( '[[File:', img, '|32x32px|link=', link or '', '|', escapedTitle, ']]' )

Latest revision as of 14:25, 18 February 2025

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

-- <pre>
-- Taken from: https://minecraft.gamepedia.com/Module:Inventory_slot
-- Massively butchered to get it working with sprites instead of a spritesheet
local p = {}

--this bit is not from minecraft gamepedia and was added here by joker876
local yesno = require('Module:Yesno')

local i18n = {
	filename = 'Invicon $1',
	legacyFilename = 'Grid $1.png',
	modLink = 'Mods/$1/$2',
	moduleAliases = [[Module:Inventory slot/Aliases]],
	prefixes = {
		any = 'Any',
		matching = 'Matching',
		damaged = 'Damaged',
	},
	suffixes = {
		be = 'BE',
		lce = 'LCE',
	},
	templateFileUrl = 'FileUrl',
}
p.i18n = i18n

local disableLinkIfNoInputs = {
	['Go Back']=1;
}

local aliases = mw.loadData( i18n.moduleAliases )
local pageName = mw.title.getCurrentTitle().text

-- Performs a simple recursive clone of a table's values
local function cloneTable( origTable )
	local newTable = {}
	for k, v in pairs( origTable ) do
		if type( v ) == 'table' then
			v = cloneTable( v )
		end
		newTable[k] = v
	end
	return newTable
end

--[[Merges a list, or inserts a string
	or table into a table
--]]
local function mergeList( parentTable, content )
	local i = #parentTable + 1
	if content[1] then
		-- Merge list into table
		for _, v in ipairs( content ) do
			parentTable[i] = v
			i = i + 1
		end
	else
		-- Add strings or tables to table
		parentTable[i] = content
	end
end

-- Creates the HTML for an item
local function makeItem( frame, i, args )
	local item = mw.html.create( 'span' ):addClass( 'invslot-item' )
	if args.imgclass then
		item:addClass( args.imgclass )
	end
	if frame.name == '' then
		return item
	end
	local category
	local title = mw.text.trim( args.title or frame.title or '' )
	local name = frame.name or ''
	local num = frame.num or 1
	local image = args.image or frame.image or nil
	local description = args.text or frame.text or ''

--this bit is not from minecraft gamepedia and was added here by joker876
	local forceNum = yesno(args.forcenum)
	
	local img, idData

    local checkIfColoredLeather = function(pStr)
        if pStr:match('%s([Hh][Ee][Ll][Mm][Ee][Tt])-(#?[0-9A-Fa-f]+)') then
    	    return pStr:match('(.*)%s([Hh][Ee][Ll][Mm][Ee][Tt])-(#?[0-9A-Fa-f]+)') 
    	elseif pStr:match('%s([Cc][Hh][Ee][Ss][Tt][Pp][Ll][Aa][Tt][Ee])-(#?[0-9A-Fa-f]+)') then
    	    return pStr:match('(.*)%s([Cc][Hh][Ee][Ss][Tt][Pp][Ll][Aa][Tt][Ee])-(#?[0-9A-Fa-f]+)')
    	elseif pStr:match('%s([Ll][Ee][Gg][Gg][Ii][Nn][Gg][Ss])-(#?[0-9A-Fa-f]+)') then
    	    return pStr:match('(.*)%s([Ll][Ee][Gg][Gg][Ii][Nn][Gg][Ss])-(#?[0-9A-Fa-f]+)')
    	elseif pStr:match('%s([Bb][Oo][Oo][Tt][Ss])-(#?[0-9A-Fa-f]+)') then
    	    return pStr:match('(.*)%s([Bb][Oo][Oo][Tt][Ss])-(#?[0-9A-Fa-f]+)')
        end
        return nil
    end

    -- Check if color data is in the name (otherwise check below if it's in the image)
	if checkIfColoredLeather(name) then
	    name, template, color = checkIfColoredLeather(name)
	end
    
    if image then
        -- Check if image name is colored leather syntax (ignore first name param that's returned)
    	if checkIfColoredLeather(image) then
    	    _, template, color = checkIfColoredLeather(image)
    	end
    	
        if image:match( '\.gif$' ) then
            img = image
        else
            img = image..".png"
        end
    else
	    img = name..'.png'
	end
	
	local link = frame.link or args.link or ''
	if link == '' then
		link = name:gsub( '^' .. i18n.prefixes.damaged .. ' ', '' )
		for _, suffix in pairs( i18n.suffixes ) do
			link = link:gsub( ' ' .. suffix .. '$', '' )
		end
	elseif ((not disableLinkIfNoInputs[name] and not args.link) or (args.link or ''):lower() == 'none') and link:lower() == 'none' then
		link = nil
	end
	if link == pageName then
		link = nil
	end
	if link == 'none' then
		link = nil
	end
	
	local formattedTitle
	local plainTitle
	if title == '' then
		plainTitle = name
		formattedTitle = name
	elseif title:lower() ~= 'none' then
		formattedTitle = title
		plainTitle = title:gsub( '\\\\', '&#92;' ):gsub( '\\&', '&#38;' )
		
		local formatPattern = '&[0-9a-fk-or]'
		if plainTitle:match( formatPattern ) then
			plainTitle = plainTitle:gsub( formatPattern, '' )
		end
		
		if plainTitle == '' then
			plainTitle = name
		else
			plainTitle = plainTitle:gsub( '&#92;', '\\' ):gsub( '&#38;', '&' )
		end
	elseif link then
		if img then
			formattedTitle = ''
		else
			plainTitle = ''
		end
	end

        if description:lower() == 'none' then description = '' end
	
	item:attr{
		['data-minetip-title'] = formattedTitle,
		['data-minetip-text'] = description
	}

	if template then
		item:tag('div'):cssText('top: 2px;left: 2px;position: absolute;'):wikitext(mw.getCurrentFrame():preprocess('{{', template:sub(1,1):upper()..template:sub(2):lower(), '|', color, '|size=32|i=1}}')):done()
	elseif img then
		-- & is re-escaped because mw.html treats attributes
		-- as plain text, but MediaWiki doesn't
		local escapedTitle = ( plainTitle or '' ):gsub( '&', '&#38;' )
		local escapedTitle = escapedTitle:gsub( 'minecraft:', 'Minecraft Wiki: ' )
		item:addClass( 'invslot-item-image' )
			:wikitext( '[[File:', img, '|32x32px|link=', link or '', '|', escapedTitle, ']]' )
	else
		local image = args.spritesheet .. 'Sprite.png'
		if link then
			item:wikitext( '[[', link, '|' )
		end
		local image
		item:node( image )
			item:wikitext( '[[', link, '|' )
	end
	
	if num and (num > 1 and num < 1000 or forceNum) then
		if img and link then
			item:wikitext( '[[', link, '|' )
		end
		local number = item
			:tag( 'span' )
				:addClass( 'invslot-stacksize' )
				:attr{ title = plainTitle }
				:wikitext( num )
		if numStyle then
			number:cssText( numStyle )
		end
		if img and link then
			item:wikitext( ']]' )
		end
	end
	
	if idData and link then
		item:wikitext( ']]' )
	end

	if link then item:wikitext('[[',link,'|'):tag('span'):cssText('position:absolute;width:100%;height:100%;top:0px;left:0px;'):done():wikitext(']]') end
	
	return item
end

-- Main entry point
function p.slot( f )
	local args = f.args or f
	if f == mw.getCurrentFrame() and args[1] == nil then
		args = f:getParent().args
	end
	
	if not args.parsed then
		args[1] = mw.text.trim( args[1] or '' )
	end
	
	local frames
	if args.parsed then
		frames = args[1]
	elseif args[1] ~= '' then
		local randomise = args.class == 'invslot-large' and 'never' or nil
		frames = p.parseFrameText( args[1], randomise, false )
	end
	local animated = frames and #frames > 1
	local imgClass = args.imgclass
	local numStyle = args.numstyle
	
	local body = mw.html.create( 'span' ):addClass( 'invslot' ):css{ ['vertical-align'] = args.align }
	if animated then
		body:addClass( 'animated' )
	end
	if args.class then
		body:addClass( args.class )
	end
	if args.style then
		body:cssText( args.style )
	end
	if ( args.default or '' ) ~= '' then
		body:css( 'background-image', f:expandTemplate{ title = i18n.templateFileUrl, args = { args.default .. '.png' } } )
	end
	
	--mw.logObject( frames )
	if not frames then
		return tostring( body )
	end
	
	local activeFrame = 1 --FC-frames.randomise == true and random( #frames ) or 1
	for i, frame in ipairs( frames ) do
		local item
		-- Table is a list, must contain subframes
		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 = makeItem( sFrame, sI, args )
				item:node( sItem )
				
				if sI == subActiveFrame then
					sItem:addClass( 'animated-active' )
				else
		            -- CUSTOM: "hidden" class is needed to hide it on mobile (since wikia doesn't allow CSS / JS on mobile)
				    sItem:addClass('hidden')
				end
			end
		else
			item = makeItem( frame, i, args )
			body:node( item )
		end
		if i == activeFrame and animated then
			item:addClass( 'animated-active' )
		elseif animated then
            -- CUSTOM: "hidden" class is needed to hide it on mobile (since wikia doesn't allow CSS / JS on mobile)
		    item:addClass('hidden')
		end
	end
	
	return tostring( body )
end

--[[Parses the frame text into a table of frames and subframes,
	expanding aliases (and optionally retaining a reference), and
	deciding if the slot can be randomised
--]]
function p.parseFrameText( framesText, randomise, aliasReference )
	local frames = { randomise = randomise }
	local subframes = {}
	local subframe
	local expandedAliases
	local splitFrames = mw.text.split( mw.text.trim( framesText ), '%s*;%s*' )
	for _, frameText in ipairs( splitFrames ) do
		frameText = frameText:gsub( '^%s*{%s*', function()
			subframe = true
			return ''
		end )
		if subframe then
			frameText = frameText:gsub( '%s*}%s*$', function()
				subframe = 'last'
				return ''
			end )
		end
		local frame = p.makeFrame( frameText )
		local newFrame = frame
		if aliases then
			local id = frame.name
			
			local alias = aliases and aliases[id]
			if alias then
				newFrame = p.getAlias( alias, frame )
				if aliasReference then
					local curFrame = #frames + 1
					local aliasData = { frame = frame, length = #newFrame }
					if subframe then
						if not subframes.aliasReference then
							subframes.aliasReference = {}
						end
						subframes.aliasReference[#subframes + 1] = aliasData
					else
						if not expandedAliases then
							expandedAliases = {}
						end
						expandedAliases[curFrame] = aliasData
					end
				end
			end
		end
		
		if subframe then
			mergeList( subframes, newFrame )
			-- Randomise starting frame for "Any *" aliases, as long as the alias is the only subframe
			if frames.randomise ~= 'never' and subframes.randomise == nil and
				frame.name:match( '^' .. i18n.prefixes.any .. ' ' ) then
				subframes.randomise = true
			else
				subframes.randomise = false
			end
			if frames.randomise ~= 'never' then
				frames.randomise = false
			end
			if subframe == 'last' then
				-- No point having a subframe containing a single frame,
				-- or the subframe being the only frame
				if #subframes == 1 or #splitFrames == i and #frames == 0 then
					mergeList( frames, subframes )
				else
					table.insert( frames, subframes )
				end
				subframes = {}
				subframe = nil
			end
		else
			-- Randomise starting frame for "Any *" aliases, as long as the alias is the only frame
			if frames.randomise == nil and frame.name:match( '^' .. i18n.prefixes.any .. ' ' ) then
				frames.randomise = true
			elseif frames.randomise ~= 'never' then
				frames.randomise = false
			end
			mergeList( frames, newFrame )
		end
	end
	
	frames.aliasReference = expandedAliases
	
	return frames
end

--[[Returns a new table with the parts of the parent frame
	added to the alias
--]]
function p.getAlias( aliasFrames, parentFrame )
	-- If alias is just a name, return the parent frame with the new name
	if type( aliasFrames ) == 'string' then
		local expandedFrame = mw.clone( parentFrame )
		expandedFrame.name = aliasFrames
		return { expandedFrame }
	end
	
	-- Single frame alias, put in list
	if aliasFrames.name then
		aliasFrames = { aliasFrames }
	end
	
	local expandedFrames = {}
	for i, aliasFrame in ipairs( aliasFrames ) do
		local expandedFrame
		if type( aliasFrame ) == 'string' then
			expandedFrame = { name = aliasFrame }
		else
			expandedFrame = cloneTable( aliasFrame )
		end
		expandedFrame.title = parentFrame.title or expandedFrame.title
		expandedFrame.num = parentFrame.num or expandedFrame.num
		expandedFrame.text = parentFrame.text or expandedFrame.text
		expandedFrame.image = parentFrame.image or expandedFrame.image
		
		expandedFrames[i] = expandedFrame
	end
	
	return expandedFrames
end

function p.expandAlias( parentFrame, alias )
	return p.getAlias( alias, parentFrame )
end

function p.stringifyFrame( frame )
	if not frame.name then
		return ''
	end
	return string.format(
		'[%s]%s:%s,%s[%s]',
		frame.title or '',
		frame.name,
		frame.num or '',
		frame.text or ''
	)
end

function p.stringifyFrames( frames )
	for i, frame in ipairs( frames ) do
		frames[i] = p.stringifyFrame( frame )
	end
	return table.concat( frames, ';' )
end

-- Splits up the frame text into its parts
function p.makeFrame( frameText )
	-- Simple frame with no parts
	if not frameText:match( '[%[:,]' ) then
		return {
			name = mw.text.trim( frameText ),
		}
	end
	
	frameText = frameText:gsub( '%s*([%[%]:,;])%s*', '%1' )
	
	local frame = {}
	frame.title = frameText:match( '^%[([^%]]+)%]' )
	
	local vanilla = { v = 1, vanilla = 1, mc = 1, minecraft = 1 }
	
	local nameStart = ( frameText:find( ':' ) or frameText:find( '%]' ) or 0 ) + 1
	if nameStart - 1 == #frameText then
		nameStart = 1
	end
	frame.name = frameText:sub( nameStart, ( frameText:find( '[,%[]', nameStart ) or 0 ) - 1 )
	
	frame.num = math.floor( frameText:match( ',(%d+)' ) or 0 )
	
	frame.text = frameText:match( '%[([^%]]+)%]$' )
	
	return frame
end
function p.getParts( frameText )
	return p.makeFrame( frameText )
end
 
return p