Module:Nightmares/Recipe table

From Tensura Wiki
Jump to navigation Jump to search

This module was adapted from: Module:Recipe table on the Minecraft Wiki. Credit goes to the original authors.


This module creates the table for {{Nightmares/Crafting}}, {{brewing}}, {{smelting}}, and {{looming}}. It can only be invoked within other modules.


-- This module was adapted from:
-- [https://minecraft.wiki/wiki/Module:Recipe table] on the Minecraft Wiki.
-- Credit goes to the original authors.


local m = {}

local i18n = {
	headingDescription = 'Description',
	headingIngredients = 'Ingredients',
	headingName = 'Name',
	headingRecipe = '[[$1]] recipe',
	moduleSlot = [[Module:Inventory slot]],
	moduleUi = [[Module:UI]],
	separator = ' +',
	setSeparator = ' or',
	tableDescription = '$1 recipes',
}
local slot = require(i18n.moduleSlot)
local prefixes = slot.i18n.prefixes

-- Lua state tracking instead of DPL
local multirow_state = {
	active = false,
	showName = nil,
	showDescription = nil
}

local function parseRecipeArgs(args, ingredientArgVals, outputArgs)
	local recipeArgs = {}
	for _, arg in pairs(ingredientArgVals) do
		recipeArgs[arg] = args[arg]
	end
	for _, arg in pairs(outputArgs) do
		recipeArgs[arg] = args[arg]
	end
	
	local parsedFrameText = {}
	local parsedRecipeArgs = {}
	for arg, frameText in pairs(recipeArgs) do
		if frameText then
			local randomise
			for _, oArg in pairs(outputArgs) do
				if arg == oArg then
					randomise = 'never'
					break
				end
			end
			local frames = not randomise and parsedFrameText[frameText]
			if not frames then
				frames = slot.parseFrameText(frameText, randomise, true)
				parsedFrameText[frameText] = frames
			end
			parsedRecipeArgs[arg] = frames
		end
	end
	
	return parsedRecipeArgs
end

-- **Re-added makeItemLinks**
function m.makeItemLinks(itemSets, removePrefixes)
	local links = {}
	for i, itemSet in ipairs(itemSets) do
		local linkSet = {}
		for i2, item in ipairs(itemSet) do
			local name = item.name
			if removePrefixes then
				name = name
					:gsub('^' .. prefixes.any .. ' ', '')
					:gsub('^' .. prefixes.matching .. ' ', '')
					:gsub('^%l', string.upper)
			end
			local disjunctionA, disjunctionB = name:match("(.-) or (.+)")
			if disjunctionA then
				linkSet[i2] = '[[' .. disjunctionA .. ']] or [[' .. disjunctionB .. ']]'
			else
				linkSet[i2] = '[[' .. name .. ']]'
			end
		end
		links[i] = table.concat(linkSet, i18n.setSeparator .. '<br>')
	end
	
	return table.concat(links, i18n.separator .. '<br>')
end

-- **Re-added makeItemSets**
function m.makeItemSets(argVals, parsedArgs)
	local usedItems = {}
	local function addItem(items, frame, alias)
		if alias then
			frame = alias.frame
		end
		
		local uniqName = (frame.mod or '') .. ':' .. frame.name
		if not usedItems[uniqName] then
			usedItems[uniqName] = true
			items[#items + 1] = frame
		end
		
		return alias and alias.length or 1
	end
	
	local itemSets = {}
	local i = 1
	for _, arg in ipairs(argVals) do
		local frames = parsedArgs[arg]
		if frames then
			local items = {}
			local frameNum = 1
			while frameNum <= #frames do
				local frame = frames[frameNum]
				if frame[1] then
					local subframeNum = 1
					while subframeNum <= #frame do
						local subframe = frame[subframeNum]
						if subframe.name ~= '' then
							local alias = frame.aliasReference and frame.aliasReference[subframeNum]
							subframeNum = subframeNum + addItem(items, subframe, alias)
						else
							subframeNum = subframeNum + 1
						end
					end
					frameNum = frameNum + 1
				elseif frame.name ~= '' then
					local alias = frames.aliasReference and frames.aliasReference[frameNum]
					frameNum = frameNum + addItem(items, frame, alias)
				else
					frameNum = frameNum + 1
				end
			end
			if #items > 0 then
				itemSets[i] = items
				i = i + 1
			end
		end
	end
	
	return itemSets
end

-- **Re-added makeHeader**
function m.makeHeader(recipeType, class, showName, showDescription, multirow)
	class = class or ''
	
	local nameCell = ''
	if showName then
		nameCell = i18n.headingName .. '!!'
	end
	
	local descriptionCell = ''
	if showDescription then
		descriptionCell = '!!class="unsortable"|' .. i18n.headingDescription
	end
	
	local recipeAttribs = ''
	if multirow then
		class = 'sortable ' .. class
		recipeAttribs = 'class="unsortable"|'
	end
	
	local header = table.concat({
		' {| class="wikitable crafting ' .. class .. '" data-description="' .. i18n.tableDescription:gsub('%$1', recipeType) .. '"',
		'!' .. nameCell ..
		i18n.headingIngredients .. '!!' ..
		recipeAttribs .. i18n.headingRecipe:gsub('%$1', recipeType) ..
		descriptionCell
	}, '\n')
	return header
end

-- **Re-added makeNameCell**
function m.makeNameCell(name, itemSets)
	if name then
		return name
	else
		return m.makeItemLinks(itemSets, true)
	end
end

-- **Re-added makeIngredientsCell**
function m.makeIngredientsCell(ingredients, itemSets)
	return ingredients or m.makeItemLinks(itemSets)
end

function m.table(args, settings)
	local f = mw.getCurrentFrame()
	
	-- Handle multirow without DPL
	local multirow = multirow_state.active
	if args.head then
		multirow_state.active = true
		multirow_state.showName = args.showname or '1'
		multirow_state.showDescription = args.showdescription or ''
	elseif args.foot then
		multirow_state.active = false
		multirow_state.showName = nil
		multirow_state.showDescription = nil
	end
	
	local showHead = args.head or not multirow
	local showFoot = args.foot or not multirow
	local showName = multirow and multirow_state.showName or args.showname
	local showDescription = multirow and multirow_state.showDescription or args.showdescription
	
	local out = {}
	if showHead then
		out[1] = m.makeHeader(args.recipeType or settings.type, args.class, showName, showDescription, multirow)
	end
	
	local ingredientArgVals = settings.ingredientArgs
	local outputArgs = settings.outputArgs
	
	local parsedRecipeArgs = args
	if not args.parsed then
		parsedRecipeArgs = parseRecipeArgs(args, ingredientArgVals, outputArgs)
	end
	
	local cells = {}
	local outputItemSets = m.makeItemSets(outputArgs, parsedRecipeArgs)
	if showName then
		cells[1] = '!' .. m.makeNameCell(args.name, outputItemSets)
	end
	
	local ingredientsItemSets = m.makeItemSets(ingredientArgVals, parsedRecipeArgs)
	cells[#cells + 1] = '|' .. m.makeIngredientsCell(args.ingredients, ingredientsItemSets)
	
	cells[#cells + 1] = '|style="padding:1px;text-align:center"|' .. require(i18n.moduleUi)[settings.uiFunc](args)
	
	if showDescription then
		cells[#cells + 1] = '|' .. (args.description or '')
	end
	
	out[#out + 1] = table.concat(cells, '\n')
	
	out[#out + 1] = showFoot and '|}' or ''
	
	return table.concat(out, '\n|-\n')
end

return m