Module:Crafting usage: Difference between revisions

Rihlsul (talk | contribs)
Trying to support the Metallurgic infuser for crafting usage sections.
AdamSauce (talk | contribs)
applied fixes from copiliot
Line 1: Line 1:
local p = {}
local p = {}
function p.dpl( f )
local args = f:getParent().args
local grid = require( 'Module:Grid' )
local ingredients = args[1] and mw.text.split( args[1], '%s*,%s*' ) or { mw.title.getCurrentTitle().text }
local matchTypes = args.match and args.match:find( ',' ) and mw.text.split( args.match, '%s*,%s*' ) or args.match


local argList = {
-- Add DPL validation
'ignoreusage', 'upcoming', 'name', 'ingredients', 'arggroups',
local function isDPLAvailable(f)
1, 2, 3, 4, 5, 6, 7, 8, 9,
    local success = pcall(function()
'A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3',
        f:callParserFunction('#dpl', {'category=Test'})
'Output', 'description', 'fixed', 'notfixed'
    end)
}
    return success
local anonToShaped = { 'A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3' }
end
local shapedToAnon = { A1 = 1, B1 = 2, C1 = 3, A2 = 4, B2 = 5, C2 = 5, A3 = 6, B3 = 7, C3 = 8 }
 
-- Add input validation with DPL check
local function validateArgs(f, args)
    if not args then
        error('Arguments table is required')
    end
    if not isDPLAvailable(f) then
        error('DynamicPageList extension is not properly configured. Please contact wiki administrator.')
    end
    return true
end
 
-- Cache frequently used functions
local text_split = mw.text.split
local text_gsplit = mw.text.gsplit
 
-- Add error handling and performance improvements
function p.dpl(f)
    -- Validate input and DPL availability
    local args = f:getParent().args
    validateArgs(f, args)
   
    -- Use local references for better performance
    local grid = require('Module:Grid')
    local ingredients = args[1] and text_split(args[1], '%s*,%s*') or {mw.title.getCurrentTitle().text}
   
    -- Add type checking
    if type(ingredients) ~= 'table' then
        error('Invalid ingredients format')
    end
 
    local matchTypes = args.match and args.match:find( ',' ) and text_split( args.match, '%s*,%s*' ) or args.match


local data = ''
    local argList = {
if args.category then
        'ignoreusage', 'upcoming', 'name', 'ingredients', 'arggroups',
data = f:callParserFunction( '#dpl', {
        1, 2, 3, 4, 5, 6, 7, 8, 9,
category = args.category,
        'A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3',
nottitleregexp = args.ignore,
        'Output', 'description', 'fixed', 'notfixed'
include = '{Crafting}:' .. table.concat( argList, ':' ),
    }
mode = 'userformat',
    local anonToShaped = { 'A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3' }
secseparators = '====',
    local shapedToAnon = { A1 = 1, B1 = 2, C1 = 3, A2 = 4, B2 = 5, C2 = 5, A3 = 6, B3 = 7, C3 = 8 }
multisecseparators = '====',
''
} )
else
-- #dpl has a limit of four, so do it in chunks of 4
for i = 1, #ingredients, 4 do
data = data .. f:callParserFunction( '#dpl', {
category = 'Recipe using ' .. table.concat( ingredients, '|Recipe using ', i, math.min( i + 3, #ingredients ) ),
nottitleregexp = args.ignore,
include = '{Crafting}:' .. table.concat( argList, ':' ),
mode = 'userformat',
secseparators = '====',
multisecseparators = '====',
''
} )
end
end
-- Comment this next line out if you're not using any aliases
local aliases = mw.loadData( 'Module:Grid/Aliases' )
local function matchPattern( ingredient, ingredientNum )
local matchType = matchTypes
if type( matchType ) == 'table' then
matchType = matchTypes[ingredientNum]
end
local pattern
local escaped = ingredient:gsub( '([%(%)])', '%%%1' )
if matchType == 'start' then
pattern = '[;:%]]%s*' .. escaped
elseif matchType == 'end' then
pattern = escaped .. '%s*[,;%[]'
elseif matchType == 'any' then
pattern = escaped
else
pattern = '[;:%]]%s*' .. escaped .. '%s*[,;%[]'
end
return pattern
end


local function compareTables( a, b )
    local data = ''
for k, v in pairs( a ) do
    if args.category then
if type( b[k] ) ~= type( v ) then
        -- Add error handling for DPL calls
return false
        local success, result = pcall(function()
end
            return f:callParserFunction('#dpl', {
if type( v ) == 'table' then
                category = args.category,
if not compareTables( v, b[k] ) then
                nottitleregexp = args.ignore,
return false
                include = '{Crafting}:' .. table.concat(argList, ':'),
end
                mode = 'userformat',
elseif v ~= b[k] then
                secseparators = '====',
return false
                multisecseparators = '====',
end
                ''
end
            })
for k, v in pairs( b ) do
        end)
if a[k] == nil then
       
return false
        if not success then
end
            return string.format(
end
                "[[Category:DPL errors]]Error processing DPL: %s",
return true
                mw.text.nowiki(result)
end
            )
        end
        data = result
    else
        -- Add chunked DPL calls with error handling
        for i = 1, #ingredients, 4 do
            local success, result = pcall(function()
                return f:callParserFunction('#dpl', {
                    category = 'Recipe using ' .. table.concat(ingredients, '|Recipe using ', i, math.min(i + 3, #ingredients)),
                    nottitleregexp = args.ignore,
                    include = '{Crafting}:' .. table.concat(argList, ':'),
                    mode = 'userformat',
                    secseparators = '====',
                    multisecseparators = '====',
                    ''
                })
            end)
           
            if not success then
                return string.format(
                    "[[Category:DPL errors]]Error processing DPL chunk %d: %s",
                    i,
                    mw.text.nowiki(result)
                )
            end
            data = data .. result
        end
    end
   
    -- Comment this next line out if you're not using any aliases
    local aliases = mw.loadData( 'Module:Grid/Aliases' )
   
    -- Add documentation
    ---@param ingredient string The ingredient to match
    ---@param ingredientNum number The ingredient number
    ---@return string pattern The regex pattern
    local function matchPattern( ingredient, ingredientNum )
        local matchType = matchTypes
        if type( matchType ) == 'table' then
            matchType = matchTypes[ingredientNum]
        end
        local pattern
        local escaped = ingredient:gsub( '([%(%)])', '%%%1' )
        if matchType == 'start' then
            pattern = '[;:%]]%s*' .. escaped
        elseif matchType == 'end' then
            pattern = escaped .. '%s*[,;%[]'
        elseif matchType == 'any' then
            pattern = escaped
        else
            pattern = '[;:%]]%s*' .. escaped .. '%s*[,;%[]'
        end
       
        return pattern
    end


local out = {}
    -- Add performance optimization for table comparison
local showDesciption
    local function compareTables( a, b )
local templates = {}
        if not a or not b then return false end
for template in mw.text.gsplit( data, '====' ) do
        for k, v in pairs( a ) do
-- If ignoreusage is empty
            if type( b[k] ) ~= type( v ) then
if template:find( '^%s*|' ) then
                return false
local tArgs = {}
            end
local i = 0
            if type( v ) == 'table' then
-- Extract the arguments from the DPL query
                if not compareTables( v, b[k] ) then
for tArg in mw.text.gsplit( template, '\n|' ) do
                    return false
i = i + 1
                end
if tArg ~= '' then
            elseif v ~= b[k] then
local key = argList[i]
                return false
tArgs[key] = tArg
            end
end
        end
end
        for k, v in pairs( b ) do
            if a[k] == nil then
local craftingArgs = {
                return false
tArgs[1] or tArgs.A1 or '' or 'Infuse', tArgs[2] or tArgs.B1 or '' or 'Input', tArgs[3] or tArgs.C1 or '',
            end
tArgs[4] or tArgs.A2 or '', tArgs[5] or tArgs.B2 or '', tArgs[6] or tArgs.C2 or '',
        end
tArgs[7] or tArgs.A3 or '', tArgs[8] or tArgs.B3 or '', tArgs[9] or tArgs.C3 or '',
        return true
Output = tArgs.Output
    end
}
local expandedFrames = {}
local hasIngredient
local argsWithIngredient = {}
local argGroups = {}
for i, v in pairs( craftingArgs ) do
if v ~= '' then
if aliases then
expandedFrames[i] = {}
local expandedFrame = {}
for frame in mw.text.gsplit( v, '%s*;%s*' ) do
local parts = grid.getParts( frame )
local alias = aliases[parts.name]
if alias then
local expandedAlias = grid.expandAlias( parts, alias ):gsub( '%s*([%[%]:,;])%s*', '%1' )
expandedFrames[i][frame] = expandedAlias:gsub( '([%(%)])', '%%%1' )
table.insert( expandedFrame, expandedAlias )
else
table.insert( expandedFrame, frame )
end
end
v = table.concat( expandedFrame, ';' )
craftingArgs[i] = v
end
if i ~= 'Output' then
local delimitedFrames = ';' .. v .. ';'
for ingredientNum, ingredient in pairs( ingredients ) do
if delimitedFrames:find( matchPattern( ingredient, ingredientNum ) ) then
if not v:find( ';' ) then
hasIngredient = 'static'
elseif not hasIngredient then
hasIngredient = 'animated'
end
argsWithIngredient[i] = true
end
end
end
if not tArgs.arggroups and hasIngredient ~= 'static' then
local _, frameCount = v:gsub( ';', '' )
if frameCount > 0 then
frameCount = frameCount + 1
local group = argGroups[frameCount]
if not group then
group = { args = {} }
argGroups[frameCount] = group
end
group.count = frameCount
group.args[i] = true
end
end
end
end
if hasIngredient then
if tArgs.description then
showDescription = true
end
if hasIngredient == 'animated' then
if tArgs.arggroups then
for argGroup in mw.text.gsplit( tArgs.arggroups, '%s*;%s*' ) do
local group = {}
local _, frameCount
for arg in mw.text.gsplit( argGroup, '%s*,%s*' ) do
if not tArgs[1] then
arg = shapedToAnon[arg]
end
if not frameCount then
_, frameCount = craftingArgs[arg]:gsub( ';', '' )
end
group[arg] = true
end
table.insert( argGroups, { count = frameCount + 1, args = group } )
end
end
for _, groupData in pairs( argGroups ) do
local frameCount = groupData.count
local group = groupData.args
local requiredFrames = {}
local requiredFramesCount = 0
for arg in pairs( group ) do
if argsWithIngredient[arg] then
local frames = craftingArgs[arg]
local frameNum = 0
for frame in mw.text.gsplit( frames, '%s*;%s*' ) do
frameNum = frameNum + 1
if not requiredFrames[frameNum] then
local delimitedFrame = ';' .. frame .. ';'
for ingredientNum, ingredient in pairs( ingredients ) do
if delimitedFrame:find( matchPattern( ingredient, ingredientNum ) ) then
requiredFrames[frameNum] = true
requiredFramesCount = requiredFramesCount + 1
end
end
end
end
end
end
-- Not all frames will be used
if requiredFramesCount > 0 and requiredFramesCount < frameCount then
for arg in pairs( group ) do
local frames = craftingArgs[arg]
local newFrames = {}
local frameNum = 0
for frame in mw.text.gsplit( frames, '%s*;%s*' ) do
frameNum = frameNum + 1
if requiredFrames[frameNum] then
table.insert( newFrames, frame )
end
end
newFrames = table.concat( newFrames, ';' )
-- If the whole expanded alias survived, collapse it again
if expandedFrames[arg] then
for frame, expandedAlias in pairs( expandedFrames[arg] ) do
--newFrames = 'blah' .. expandedAlias
newFrames = newFrames:gsub( expandedAlias, frame )
end
end
local tArg = arg
if arg ~= 'Output' and not tArgs[1] then
tArg = anonToShaped[arg]
end
tArgs[tArg] = newFrames
end
-- Let Module:Crafting handle the name and ingredients columns
tArgs.name = nil
tArgs.ingredients = nil
end
end
end
tArgs.nocat = '1'


local found = false
    -- Add result caching for frequently accessed data
for i, v in ipairs( templates ) do
    local cache = setmetatable({}, {__mode = 'kv'})
if compareTables( v, tArgs ) then
    local function getCachedResult(key, fn, ...)
found = true
        if not cache[key] then
break
            cache[key] = fn(...)
end
        end
end
        return cache[key]
if not found then
    end
table.insert( templates, tArgs )
 
end
    local out = {}
end
    local showDesciption
end
    local templates = {}
end
    for template in text_gsplit( data, '====' ) do
if #templates == 0 then
        -- If ignoreusage is empty
return '[[Category:Empty crafting usage]]'
        if template:find( '^%s*|' ) then
end
            local tArgs = {}
            local i = 0
templates[1].head = '1'
            -- Extract the arguments from the DPL query
templates[1].showname = '1'
            for tArg in text_gsplit( template, '\n|' ) do
if showDescription and args.showdesciption ~= '0' or args.showdesciption == '1' then
                i = i + 1
templates[1].showdescription = '1'
                if tArg ~= '' then
end
                    local key = argList[i]
if not args.continue then
                    tArgs[key] = tArg
templates[#templates].foot = '1'
                end
end
            end
           
local crafting = require( 'Module:Crafting' )
            local craftingArgs = {
local out = {}
                tArgs[1] or tArgs.A1 or '' or 'Infuse', tArgs[2] or tArgs.B1 or '' or 'Input', tArgs[3] or tArgs.C1 or '',
for i, v in ipairs( templates ) do
                tArgs[4] or tArgs.A2 or '', tArgs[5] or tArgs.B2 or '', tArgs[6] or tArgs.C2 or '',
table.insert( out, crafting.table( v ) )
                tArgs[7] or tArgs.A3 or '', tArgs[8] or tArgs.B3 or '', tArgs[9] or tArgs.C3 or '',
end
                Output = tArgs.Output
            }
return table.concat( out, '\n' )
           
            local expandedFrames = {}
            local hasIngredient
            local argsWithIngredient = {}
            local argGroups = {}
            for i, v in pairs( craftingArgs ) do
                if v ~= '' then
                    if aliases then
                        expandedFrames[i] = {}
                        local expandedFrame = {}
                        for frame in text_gsplit( v, '%s*;%s*' ) do
                            local parts = grid.getParts( frame )
                            local alias = aliases[parts.name]
                            if alias then
                                local expandedAlias = grid.expandAlias( parts, alias ):gsub( '%s*([%[%]:,;])%s*', '%1' )
                                expandedFrames[i][frame] = expandedAlias:gsub( '([%(%)])', '%%%1' )
                                table.insert( expandedFrame, expandedAlias )
                            else
                                table.insert( expandedFrame, frame )
                            end
                        end
                       
                        v = table.concat( expandedFrame, ';' )
                        craftingArgs[i] = v
                    end
                    if i ~= 'Output' then
                        local delimitedFrames = ';' .. v .. ';'
                        for ingredientNum, ingredient in pairs( ingredients ) do
                            if delimitedFrames:find( matchPattern( ingredient, ingredientNum ) ) then
                                if not v:find( ';' ) then
                                    hasIngredient = 'static'
                                elseif not hasIngredient then
                                    hasIngredient = 'animated'
                                end
                               
                                argsWithIngredient[i] = true
                            end
                        end
                    end
                   
                    if not tArgs.arggroups and hasIngredient ~= 'static' then
                        local _, frameCount = v:gsub( ';', '' )
                        if frameCount > 0 then
                            frameCount = frameCount + 1
                            local group = argGroups[frameCount]
                            if not group then
                                group = { args = {} }
                                argGroups[frameCount] = group
                            end
                            group.count = frameCount
                            group.args[i] = true
                        end
                    end
                end
            end
           
            if hasIngredient then
                if tArgs.description then
                    showDescription = true
                end
               
                if hasIngredient == 'animated' then
                    if tArgs.arggroups then
                        for argGroup in text_gsplit( tArgs.arggroups, '%s*;%s*' ) do
                            local group = {}
                            local _, frameCount
                            for arg in text_gsplit( argGroup, '%s*,%s*' ) do
                                if not tArgs[1] then
                                    arg = shapedToAnon[arg]
                                end
                                if not frameCount then
                                    _, frameCount = craftingArgs[arg]:gsub( ';', '' )
                                end
                                group[arg] = true
                            end
                            table.insert( argGroups, { count = frameCount + 1, args = group } )
                        end
                    end
                   
                    for _, groupData in pairs( argGroups ) do
                        local frameCount = groupData.count
                        local group = groupData.args
                        local requiredFrames = {}
                        local requiredFramesCount = 0
                        for arg in pairs( group ) do
                            if argsWithIngredient[arg] then
                                local frames = craftingArgs[arg]
                                local frameNum = 0
                                for frame in text_gsplit( frames, '%s*;%s*' ) do
                                    frameNum = frameNum + 1
                                    if not requiredFrames[frameNum] then
                                        local delimitedFrame = ';' .. frame .. ';'
                                        for ingredientNum, ingredient in pairs( ingredients ) do
                                            if delimitedFrame:find( matchPattern( ingredient, ingredientNum ) ) then
                                                requiredFrames[frameNum] = true
                                                requiredFramesCount = requiredFramesCount + 1
                                            end
                                        end
                                    end
                                end
                            end
                        end
                       
                        -- Not all frames will be used
                        if requiredFramesCount > 0 and requiredFramesCount < frameCount then
                            for arg in pairs( group ) do
                                local frames = craftingArgs[arg]
                                local newFrames = {}
                                local frameNum = 0
                                for frame in text_gsplit( frames, '%s*;%s*' ) do
                                    frameNum = frameNum + 1
                                    if requiredFrames[frameNum] then
                                        table.insert( newFrames, frame )
                                    end
                                end
                                newFrames = table.concat( newFrames, ';' )
                               
                                -- If the whole expanded alias survived, collapse it again
                                if expandedFrames[arg] then
                                    for frame, expandedAlias in pairs( expandedFrames[arg] ) do
                                        --newFrames = 'blah' .. expandedAlias
                                        newFrames = newFrames:gsub( expandedAlias, frame )
                                    end
                                end
                               
                                local tArg = arg
                                if arg ~= 'Output' and not tArgs[1] then
                                    tArg = anonToShaped[arg]
                                end
                                tArgs[tArg] = newFrames
                            end
                           
                            -- Let Module:Crafting handle the name and ingredients columns
                            tArgs.name = nil
                            tArgs.ingredients = nil
                        end
                    end
                end
               
                tArgs.nocat = '1'
 
                local found = false
                for i, v in ipairs( templates ) do
                    if compareTables( v, tArgs ) then
                        found = true
                        break
                    end
                end
                if not found then
                    table.insert( templates, tArgs )
                end
            end
        end
    end
 
    -- Add error handling for empty results
    if #templates == 0 then
        return '[[Category:Empty crafting usage]]'
    end
   
    templates[1].head = '1'
    templates[1].showname = '1'
    if showDescription and args.showdesciption ~= '0' or args.showdesciption == '1' then
        templates[1].showdescription = '1'
    end
    if not args.continue then
        templates[#templates].foot = '1'
    end
   
    local crafting = require( 'Module:Crafting' )
    local out = {}
    for i, v in ipairs( templates ) do
        table.insert( out, crafting.table(v) )
    end
   
    return table.concat( out, '\n' )
end
end
return p
return p

Revision as of 08:20, 5 January 2025

Documentation for this module may be created at Module:Crafting usage/doc

local p = {}

-- Add DPL validation
local function isDPLAvailable(f)
    local success = pcall(function()
        f:callParserFunction('#dpl', {'category=Test'})
    end)
    return success
end

-- Add input validation with DPL check
local function validateArgs(f, args)
    if not args then
        error('Arguments table is required')
    end
    if not isDPLAvailable(f) then
        error('DynamicPageList extension is not properly configured. Please contact wiki administrator.')
    end
    return true
end

-- Cache frequently used functions
local text_split = mw.text.split
local text_gsplit = mw.text.gsplit

-- Add error handling and performance improvements
function p.dpl(f)
    -- Validate input and DPL availability
    local args = f:getParent().args
    validateArgs(f, args)
    
    -- Use local references for better performance
    local grid = require('Module:Grid')
    local ingredients = args[1] and text_split(args[1], '%s*,%s*') or {mw.title.getCurrentTitle().text}
    
    -- Add type checking
    if type(ingredients) ~= 'table' then
        error('Invalid ingredients format')
    end

    local matchTypes = args.match and args.match:find( ',' ) and text_split( args.match, '%s*,%s*' ) or args.match

    local argList = {
        'ignoreusage', 'upcoming', 'name', 'ingredients', 'arggroups',
        1, 2, 3, 4, 5, 6, 7, 8, 9,
        'A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3',
        'Output', 'description', 'fixed', 'notfixed'
    }
    local anonToShaped = { 'A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3' }
    local shapedToAnon = { A1 = 1, B1 = 2, C1 = 3, A2 = 4, B2 = 5, C2 = 5, A3 = 6, B3 = 7, C3 = 8 }

    local data = ''
    if args.category then
        -- Add error handling for DPL calls
        local success, result = pcall(function()
            return f:callParserFunction('#dpl', {
                category = args.category,
                nottitleregexp = args.ignore,
                include = '{Crafting}:' .. table.concat(argList, ':'),
                mode = 'userformat',
                secseparators = '====',
                multisecseparators = '====',
                ''
            })
        end)
        
        if not success then
            return string.format(
                "[[Category:DPL errors]]Error processing DPL: %s", 
                mw.text.nowiki(result)
            )
        end
        data = result
    else
        -- Add chunked DPL calls with error handling
        for i = 1, #ingredients, 4 do
            local success, result = pcall(function()
                return f:callParserFunction('#dpl', {
                    category = 'Recipe using ' .. table.concat(ingredients, '|Recipe using ', i, math.min(i + 3, #ingredients)),
                    nottitleregexp = args.ignore,
                    include = '{Crafting}:' .. table.concat(argList, ':'),
                    mode = 'userformat',
                    secseparators = '====',
                    multisecseparators = '====',
                    ''
                })
            end)
            
            if not success then
                return string.format(
                    "[[Category:DPL errors]]Error processing DPL chunk %d: %s",
                    i,
                    mw.text.nowiki(result)
                )
            end
            data = data .. result
        end
    end
    
    -- Comment this next line out if you're not using any aliases
    local aliases = mw.loadData( 'Module:Grid/Aliases' )
    
    -- Add documentation
    ---@param ingredient string The ingredient to match
    ---@param ingredientNum number The ingredient number
    ---@return string pattern The regex pattern
    local function matchPattern( ingredient, ingredientNum )
        local matchType = matchTypes
        if type( matchType ) == 'table' then
            matchType = matchTypes[ingredientNum]
        end
        local pattern
        local escaped = ingredient:gsub( '([%(%)])', '%%%1' )
        if matchType == 'start' then
            pattern = '[;:%]]%s*' .. escaped
        elseif matchType == 'end' then
            pattern = escaped .. '%s*[,;%[]'
        elseif matchType == 'any' then
            pattern = escaped
        else
            pattern = '[;:%]]%s*' .. escaped .. '%s*[,;%[]'
        end
        
        return pattern
    end

    -- Add performance optimization for table comparison
    local function compareTables( a, b )
        if not a or not b then return false end
        for k, v in pairs( a ) do
            if type( b[k] ) ~= type( v ) then
                return false
            end
            if type( v ) == 'table' then
                if not compareTables( v, b[k] ) then
                    return false
                end
            elseif v ~= b[k] then
                return false
            end
        end
        for k, v in pairs( b ) do
            if a[k] == nil then
                return false
            end
        end
        return true
    end

    -- Add result caching for frequently accessed data
    local cache = setmetatable({}, {__mode = 'kv'})
    local function getCachedResult(key, fn, ...)
        if not cache[key] then
            cache[key] = fn(...)
        end
        return cache[key]
    end

    local out = {}
    local showDesciption
    local templates = {}
    for template in text_gsplit( data, '====' ) do
        -- If ignoreusage is empty
        if template:find( '^%s*|' ) then
            local tArgs = {}
            local i = 0
            -- Extract the arguments from the DPL query
            for tArg in text_gsplit( template, '\n|' ) do
                i = i + 1
                if tArg ~= '' then
                    local key = argList[i]
                    tArgs[key] = tArg
                end
            end
            
            local craftingArgs = {
                tArgs[1] or tArgs.A1 or '' or 'Infuse', tArgs[2] or tArgs.B1 or '' or 'Input', tArgs[3] or tArgs.C1 or '',
                tArgs[4] or tArgs.A2 or '', tArgs[5] or tArgs.B2 or '', tArgs[6] or tArgs.C2 or '',
                tArgs[7] or tArgs.A3 or '', tArgs[8] or tArgs.B3 or '', tArgs[9] or tArgs.C3 or '',
                Output = tArgs.Output
            }
            
            local expandedFrames = {}
            local hasIngredient
            local argsWithIngredient = {}
            local argGroups = {}
            for i, v in pairs( craftingArgs ) do
                if v ~= '' then
                    if aliases then
                        expandedFrames[i] = {}
                        local expandedFrame = {}
                        for frame in text_gsplit( v, '%s*;%s*' ) do
                            local parts = grid.getParts( frame )
                            local alias = aliases[parts.name]
                            if alias then
                                local expandedAlias = grid.expandAlias( parts, alias ):gsub( '%s*([%[%]:,;])%s*', '%1' )
                                expandedFrames[i][frame] = expandedAlias:gsub( '([%(%)])', '%%%1' )
                                table.insert( expandedFrame, expandedAlias )
                            else
                                table.insert( expandedFrame, frame )
                            end
                        end
                        
                        v = table.concat( expandedFrame, ';' )
                        craftingArgs[i] = v
                    end
                    if i ~= 'Output' then
                        local delimitedFrames = ';' .. v .. ';'
                        for ingredientNum, ingredient in pairs( ingredients ) do
                            if delimitedFrames:find( matchPattern( ingredient, ingredientNum ) ) then
                                if not v:find( ';' ) then
                                    hasIngredient = 'static'
                                elseif not hasIngredient then
                                    hasIngredient = 'animated'
                                end
                                
                                argsWithIngredient[i] = true
                            end
                        end
                    end
                    
                    if not tArgs.arggroups and hasIngredient ~= 'static' then
                        local _, frameCount = v:gsub( ';', '' )
                        if frameCount > 0 then
                            frameCount = frameCount + 1
                            local group = argGroups[frameCount]
                            if not group then
                                group = { args = {} }
                                argGroups[frameCount] = group
                            end
                            group.count = frameCount
                            group.args[i] = true
                        end
                    end
                end
            end
            
            if hasIngredient then
                if tArgs.description then
                    showDescription = true
                end
                
                if hasIngredient == 'animated' then
                    if tArgs.arggroups then
                        for argGroup in text_gsplit( tArgs.arggroups, '%s*;%s*' ) do
                            local group = {}
                            local _, frameCount
                            for arg in text_gsplit( argGroup, '%s*,%s*' ) do
                                if not tArgs[1] then
                                    arg = shapedToAnon[arg]
                                end
                                if not frameCount then
                                    _, frameCount = craftingArgs[arg]:gsub( ';', '' )
                                end
                                group[arg] = true
                            end
                            table.insert( argGroups, { count = frameCount + 1, args = group } )
                        end
                    end
                    
                    for _, groupData in pairs( argGroups ) do
                        local frameCount = groupData.count
                        local group = groupData.args
                        local requiredFrames = {}
                        local requiredFramesCount = 0
                        for arg in pairs( group ) do
                            if argsWithIngredient[arg] then
                                local frames = craftingArgs[arg]
                                local frameNum = 0
                                for frame in text_gsplit( frames, '%s*;%s*' ) do
                                    frameNum = frameNum + 1
                                    if not requiredFrames[frameNum] then
                                        local delimitedFrame = ';' .. frame .. ';'
                                        for ingredientNum, ingredient in pairs( ingredients ) do
                                            if delimitedFrame:find( matchPattern( ingredient, ingredientNum ) ) then
                                                requiredFrames[frameNum] = true
                                                requiredFramesCount = requiredFramesCount + 1
                                            end
                                        end
                                    end
                                end
                            end
                        end
                        
                        -- Not all frames will be used
                        if requiredFramesCount > 0 and requiredFramesCount < frameCount then
                            for arg in pairs( group ) do
                                local frames = craftingArgs[arg]
                                local newFrames = {}
                                local frameNum = 0
                                for frame in text_gsplit( frames, '%s*;%s*' ) do
                                    frameNum = frameNum + 1
                                    if requiredFrames[frameNum] then
                                        table.insert( newFrames, frame )
                                    end
                                end
                                newFrames = table.concat( newFrames, ';' )
                                
                                -- If the whole expanded alias survived, collapse it again
                                if expandedFrames[arg] then
                                    for frame, expandedAlias in pairs( expandedFrames[arg] ) do
                                        --newFrames = 'blah' .. expandedAlias
                                        newFrames = newFrames:gsub( expandedAlias, frame )
                                    end
                                end
                                
                                local tArg = arg
                                if arg ~= 'Output' and not tArgs[1] then
                                    tArg = anonToShaped[arg]
                                end
                                tArgs[tArg] = newFrames
                            end
                            
                            -- Let Module:Crafting handle the name and ingredients columns
                            tArgs.name = nil
                            tArgs.ingredients = nil
                        end
                    end
                end
                
                tArgs.nocat = '1'

                local found = false
                for i, v in ipairs( templates ) do
                    if compareTables( v, tArgs ) then
                        found = true
                        break
                    end
                end
                if not found then
                    table.insert( templates, tArgs )
                end
            end
        end
    end

    -- Add error handling for empty results
    if #templates == 0 then
        return '[[Category:Empty crafting usage]]'
    end
    
    templates[1].head = '1'
    templates[1].showname = '1'
    if showDescription and args.showdesciption ~= '0' or args.showdesciption == '1' then
        templates[1].showdescription = '1'
    end
    if not args.continue then
        templates[#templates].foot = '1'
    end
    
    local crafting = require( 'Module:Crafting' )
    local out = {}
    for i, v in ipairs( templates ) do
        table.insert( out, crafting.table(v) )
    end
    
    return table.concat( out, '\n' )
end

return p

Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Need wiki hosting?

Do you need a wiki for your Minecraft mod/gaming wiki? We'll host it for free! Contact us.

Other wikis

Indie-game wikis
Powered by Indie Wikis