Attention Mobile version Mobile Users! Registration for Mobile 1.3 Beta Testing is live! Register here!

Module:Crafts/ingredient

From Terraria Wiki
Jump to: navigation, search

Internal sub-module pertaining to the set of {{crafts}}.

Normalizes an ingredients input and outputs it in a properly formatted way.


local item_link = require('Module:Item').go

-- credit: http://richard.warburton.it
-- this version is with trim.
local function explode(div,str) 
	if (div=='') then return false end
	local pos,arr = 0,{}
	-- for each divider found
	for st,sp in function() return string.find(str,div,pos,true) end do
		table.insert(arr,mw.text.trim(string.sub(str,pos,st-1))) -- Attach chars left of current divider
		pos = sp + 1 -- Jump past current divider
	end
	table.insert(arr, mw.text.trim(string.sub(str,pos))) -- Attach chars right of last divider
	return arr
end

local metals = {
	['Copper/Tin'] = 1,
	['Silver/Tungsten'] = 1,
	['Gold/Platinum'] = 1,
	['Iron/Lead'] = 1,
	['Cobalt/Palladium'] = 1,
	['Mythril/Orichalcum'] = 1,
	['Adamantite/Titanium'] = 1,
	['Tin/Copper'] = 2,
	['Tungsten/Silver'] = 2,
	['Platinum/Gold'] = 2,
	['Lead/Iron'] = 2,
	['Palladium/Cobalt'] = 2,
	['Orichalcum/Mythril'] = 2,
	['Titanium/Adamantite'] = 2,
}

-- retuan a array of itemname, split xxx/yyy to item1=xxx, item2=yyy. If it's something like "Lead/Iron Bar", it will normalize as item1 = Iron Bar, item2 = Lead Bar.
local function split(name)
	local count = select(2, name:gsub("/", "/", 2))
	if count == 0 then
		-- only 1 item
		return {mw.text.trim(name)}
	elseif count == 1 then
		-- 2 items
		local item1a, item1b, item2a, item2b = name:match("^%s*(%S+)%s*(.-)/%s*(%S+)%s*(.-)$")
		local x = metals[item1a..'/'..item2a]
		if tostring(item1b) == '' and x then
			item1b = item2b
		end
		if x == 2 then
			return {mw.text.trim(item2a..' '..item2b), mw.text.trim(item1a..' '..item1b)}
		else
			return {mw.text.trim(item1a..' '..item1b), mw.text.trim(item2a..' '..item2b)}
		end
	else
		-- 3 or more items
		return explode('/', name)
	end
end

-- return 1 or 2 value(s), when input is name[note], return item, note.
function itemname(str)
		local item, note = str:match("^(.-)(%b[])$")
		if item then
			return item, note
		else
			return str
		end
end

-- main return object 
return {

-- normalize ingredient name input, Lead Bar=>¦Lead Bar¦, Iron/Lead Bar => ¦Iron Bar¦Lead Bar¦, Lead/Iron Bar => ¦Iron Bar¦Lead Bar¦ ....
normalize = function(frame)
	local result = '¦'
	for k, v in pairs(split(frame.args[1])) do
		result = result .. itemname(v) .. '¦'
	end
	return result
end,

-- output ingredients list (<ul> element), like function go.
format = function(frame, ingredients_info, page)
	
	local _input = ingredients_info
	local _basepage = page

	local icons

	local result = ''
	-- for each ingredient × amount
	for name, amount in _input:gmatch("(.-)¦(.-)¶") do
		local li = nil
		local icons = ''
		local note = nil
		-- every item in item1/item2/item3...
		for k, v in pairs(split(name)) do
			local item, note = itemname(v)
			if item == _basepage then
				icons = 'no'
			end
			if li then
				li = li .. " ''or'' " .. item_link(frame, {item, frame:expandTemplate{ title = 'tr', args = {item} },icons=icons, note=note, small='y' } )
			else
				li = item_link(frame, {item,frame:expandTemplate{ title = 'tr', args = {item} }, icons=icons, note=note, small='y' } )
			end
		end
		-- amount
		if tonumber(amount) ~= 1 then
			li = li .. '&nbsp;(' .. amount .. ')'
		end
		result = result .. mw.text.tag('li', nil, li)
	end
	return mw.text.tag('ul', nil, result)

end,

}