Minecraft Wiki沙盒
欢迎来到中文Minecraft Wiki的公共沙盒。您可以在此页面上进行测试性编辑,但我们仍然建议在此处进行有建设性的编辑或翻译较短的条目。要编辑此页面,请点击上方的“编辑”铅笔按钮,或点击此处。在进行更改后,您可以点击编辑框下面的“显示预览”按钮来预览您的编辑,然后在相同位置点击“保存页面”按钮来保存编辑。
请注意,对此页面的更改不会被长期保留,因为此页面仅供测试编辑或翻译较短的条目之用。您也可以创建此页面的子页面(例如,Module:Sandbox/测试)来进行长期的项目,但它们仍然会在社区认定其过期后被删除。任何不具建设性的内容随时都可能会被清理。另外,如果您已注册账号,可以在自己的个人页面下创建您的个人沙盒,并且不用担心您的编辑会被清理。
您在编辑包括本页面在内的所有Wiki页面时都必须遵守相关的Wiki条例、格式指导和书面汉语指导等规范指导,否则您的编辑会被回退,您也可能会遭到警告甚至封禁处理。若有任何疑问,请到讨论页或社区专页提出。若需要联系管理员,请到管理员告示板提出请求。
所有子页面:
- Module:Sandbox/doc
最后编辑于3年6天7小时53分前 - Module:Sandbox/tooBright
最后编辑于2年6周10小时25分前 - Module:Sandbox/Chixvv/LootChest/config
最后编辑于2年4周1天17小时28分前 - Module:Sandbox/Chixvv/LootChest
最后编辑于2年2周4天6小时22分前 - Module:Sandbox/Version nav
最后编辑于1年48周1天14小时29分前 - Module:Sandbox/AllConversion
最后编辑于1年39周4天13小时58分前 - Module:Sandbox/AllConversion/doc
最后编辑于1年39周4天13小时43分前 - Module:Sandbox/AllConversion2/JE IDs
最后编辑于1年38周15小时40分前 - Module:Sandbox/AllConversion2/BE Blocks
最后编辑于1年38周13小时8分前 - Module:Sandbox/AllConversion2/BE Items
最后编辑于1年36周6天14小时58分前 - Module:Sandbox/AllConversion2/BE lang
最后编辑于1年36周5天18小时16分前 - Module:Sandbox/AllConversion2/data
最后编辑于1年36周5天17小时9分前 - Module:Sandbox/AllConversion2/Data Table
最后编辑于1年36周5天13小时16分前 - Module:Sandbox/AllConversion2/JE lang
最后编辑于1年36周5天11小时48分前 - Module:Sandbox/AllConversion2
最后编辑于1年36周5天11小时47分前 - Module:Sandbox/Command/Syntax
最后编辑于1年30周2天13小时39分前 - Module:Sandbox/Anterdc99/Crafting
最后编辑于39周6天23小时53分前 - Module:Sandbox/Anterdc99/Crafting usage
最后编辑于39周6天23小时53分前 - Module:Sandbox/Anterdc99
最后编辑于29周2天12小时34分前 - Module:Sandbox/Infobox
最后编辑于20周1天16小时38分前 - Module:Sandbox/LootChest
最后编辑于18周4天23小时40分前 - Module:Sandbox/GetSubpages
最后编辑于13周1天22小时39分前 - Module:Sandbox/HistoryM
最后编辑于10周3天19小时28分前 - Module:Sandbox/AllConversion/data
最后编辑于5周4天13小时7分前 - Module:Sandbox/GetSubpages/doc
最后编辑于5周18小时13分前 - Module:Sandbox/AllConversion2/doc
最后编辑于3周1天20小时18分前
若上述页面信息不准确,请点击此处刷新页面。
local p = {}
local i18n = {
emptyCategory = '空合成用途',
moduleCrafting = [[Module:Crafting]],
moduleSlot = [[Module:Inventory slot]],
queryCategory = 'Recipe using $1',
templateCrafting = 'Crafting',
}
p.i18n = i18n
local text = mw.text
local slot = require( i18n.moduleSlot )
local crafting = require( i18n.moduleCrafting )
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',
'A1title', 'A1link', 'B1title', 'B1link', 'C1title', 'C1link',
'A2title', 'A2link', 'B2title', 'B2link', 'C2title', 'C2link',
'A3title', 'A3link', 'B3title', 'B3link', 'C3title', 'C3link',
'Otitle', 'Olink',
'%PAGE%',
}
local prefixes = slot.i18n.prefixes
local function map(tbl, func)
local newtbl = {}
for i,v in pairs(tbl) do
newtbl[i] = func(v)
end
return newtbl
end
-- Flatten a nested array, only doing the numerically-indexed parts.
local function flatten(tbl)
local newtbl = {}
local function _flat(arr)
for _, v in ipairs(arr) do
if type(v) == "table" and v[1] then
_flat(v)
else
table.insert(newtbl, v)
end
end
end
_flat(tbl)
return newtbl
end
--[[Escapes special characters in ingredient names, and returns the correct
pattern depending on the match type
--]]
local function createIngredientPatterns( ingredients, matchTypes )
local patternChars = {
['^'] = '%^';
['$'] = '%$';
['('] = '%(';
[')'] = '%)';
['%'] = '%%';
['.'] = '%.';
['['] = '%[';
[']'] = '%]';
['*'] = '%*';
['+'] = '%+';
['-'] = '%-';
['?'] = '%?';
['\0'] = '%z';
}
local patterns = {}
for i, ingredient in ipairs( ingredients ) do
local escaped = ingredient:gsub( '([^%w])', patternChars )
if not matchTypes then
patterns[i] = '%z' .. escaped .. '%z'
else
local matchType = matchTypes[i] or matchTypes
if matchType == 'start' then
patterns[i] = '%z' .. escaped
elseif matchType == 'end' then
patterns[i] = escaped .. '%z'
else
patterns[i] = escaped
end
end
end
return patterns
end
--[[Extracts the anonymous pipe-delimited arguments from the
DPL query into a table with the corresponding keys, skipping
templates with `ignoreusage` set, and skipping duplicate templates
--]]
local extractArgs
do
local seen = {}
extractArgs = function( template )
-- Check for duplicate template or `ignoreusage` arg
if seen[template] or not template:find( '^\n|' ) then
return
end
seen[template] = true
local tArgs = {}
local i = 1
for arg in text.gsplit( template, '\n|' ) do
if arg ~= '' then
tArgs[argList[i]] = arg
end
i = i + 1
end
tArgs.nocat = '1'
return tArgs
end
end
--[[Loops through the crafting args and parses them, with alias reference data
Identical slots reuse the same table, to allow them to be compared like strings
--]]
local function parseCraftingArgs( cArgs )
local parsedFrameText = {}
local parsedCArgs = {}
for arg, frameText in pairs( cArgs ) do
if frameText then
local randomise = arg == 'Output' and 'never' or nil
local frames = not randomise and parsedFrameText[frameText]
if not frames then
frames = slot.parseFrameText( frameText, randomise, true )
parsedFrameText[frameText] = frames
end
parsedCArgs[arg] = frames
end
end
return parsedCArgs
end
-- Loops through the wanted ingredients, and checks if the name contains it
-- REQUIREMENT: name starts and ends with the NUL (\0) character. Simplifies operation
-- for multiple names in the variable.
local function containsIngredients( name, ingredientPatterns )
for _, ingredient in pairs( ingredientPatterns ) do
if name:find( ingredient ) then
return true
end
end
return false
end
--[[Loops through the crafting ingredients and find which parameters and
frames contain the wanted ingredients
Returns a table if any matches are found, the table contains tables of
required frame numbers, or true if all of them are required
--]]
local function findRequiredFrameNums( parsedCArgs, ingredientPatterns )
local requiredFrameNums = {}
local hasRequiredFrames
for arg, frames in pairs( parsedCArgs ) do
if arg ~= 'Output' then
local requiredFrames = {}
local count = 0
for i, frame in ipairs( frames ) do
-- Guess what? If we only take the first we lose the subframes.
-- And then 'Cobblestone or Blackstone' starts breaking.
local tframe = frame[1] and flatten(frame) or { frame }
local names = '\0' .. table.concat(map(tframe, function (fr) return type(fr) == 'table' and fr.name or '' end), '\0') .. '\0'
if containsIngredients( names, ingredientPatterns ) then
requiredFrames[i] = true
count = count + 1
end
end
if count > 0 then
if count == #frames then
return true
end
hasRequiredFrames = true
requiredFrames.count = count
requiredFrameNums[arg] = requiredFrames
end
end
end
return hasRequiredFrames and requiredFrameNums
end
--[[Generates the argument groups, either using the template's specified
groups, or automatically based on the number of frames in each slot
--]]
local function generateArgGroups( predefinedArgGroups, parsedCArgs )
local argGroups = {}
if predefinedArgGroups or '' ~= '' then
local i = 1
for argGroup in text.gsplit( predefinedArgGroups, '%s*;%s*' ) do
local groupData = { args = {} }
for arg in text.gsplit( argGroup, '%s*,%s*' ) do
arg = tonumber( arg ) or arg
if not groupData.count then
groupData.count = #parsedCArgs[arg]
end
groupData.args[arg] = true
end
argGroups[i] = groupData
i = i + 1
end
else
for arg, frames in pairs( parsedCArgs ) do
local framesLen = #frames
if framesLen > 0 then
local groupName = framesLen
local alias = frames.aliasReference and frames.aliasReference[1]
if alias and alias.length == framesLen and
alias.frame.name:find( '^' .. prefixes.any .. ' ' )
then
groupName = alias.frame.name
end
local groupData = argGroups[groupName]
if not groupData then
groupData = {
args = {},
count = framesLen
}
argGroups[groupName] = groupData
end
groupData.args[arg] = true
end
end
end
return argGroups
end
--[[Adds together the required frames from each slot in this group
to get the total amount of frames which are relevant
Returns a table with the relevant frame numbers, if any are relevant
--]]
local function findRelevantFrameNums( requiredFrameNumData, group )
local relevantFrameNums = {}
local hasRelevantFrames
for arg in pairs( group ) do
local requiredFrameNums = requiredFrameNumData[arg]
if requiredFrameNums and arg ~= 'Output' then
for frameNum in pairs( requiredFrameNums ) do
-- Have to use pairs as it contains a non-sequential set of numbers
-- so we have to skip over the extra data in the table
if frameNum ~= 'count' then
hasRelevantFrames = true
relevantFrameNums[frameNum] = true
end
end
relevantFrameNums.count = math.max(
requiredFrameNums.count or 0,
relevantFrameNums.count or 0
)
end
end
return hasRelevantFrames and relevantFrameNums
end
--[[Loops through the relevant frame numbers and extracts them
into a new table, taking care of moving any alias references
and cleaning up any unnecessary subframes
--]]
function p.extractRelevantFrames( relevantFrameNums, frames )
local relevantFrames = { randomise = frames.randomise }
local newFrameNum = 1
for frameNum, frame in ipairs( frames ) do
local relevantFrame = relevantFrameNums == true or relevantFrameNums[frameNum]
if relevantFrame then
if not frame[1] then
local alias = frames.aliasReference and frames.aliasReference[frameNum]
local moveAlias = true
if alias and relevantFrameNums ~= true then
for i = frameNum, alias.length do
if not relevantFrameNums[i] then
moveAlias = false
break
end
end
end
if alias and moveAlias then
if not relevantFrames.aliasReference then
relevantFrames.aliasReference = {}
end
relevantFrames.aliasReference[newFrameNum] = alias
end
end
relevantFrames[newFrameNum] = frame
newFrameNum = newFrameNum + 1
end
end
-- Move frames in subframe to main frames, if the subframe
-- is the only frame
if not relevantFrames[2] and relevantFrames[1][1] then
relevantFrames = relevantFrames[1]
end
return relevantFrames
end
--[[Works out what data is relevant to the requested ingredients
If the template contains any of the ingredients, returns it with any
necessary modifications, and with the crafting arguments parsed
--]]
function p.processTemplate( tArgs, ingredientPatterns )
local cArgs = {}
for i, v in pairs( crafting.cArgVals ) do
cArgs[i] = tArgs[i] or tArgs[v]
end
cArgs.Output = tArgs.Output
local parsedCArgs = parseCraftingArgs( cArgs )
local requiredFrameNumData = findRequiredFrameNums( parsedCArgs, ingredientPatterns )
if not requiredFrameNumData then
return
end
local newCArgs
local modified
if requiredFrameNumData == true then
newCArgs = parsedCArgs
else
local argGroups = generateArgGroups( tArgs.arggroups, parsedCArgs )
newCArgs = {}
for _, groupData in pairs( argGroups ) do
local group = groupData.args
local relevantFrameNums = findRelevantFrameNums( requiredFrameNumData, group )
if not relevantFrameNums then
for arg in pairs( group ) do
newCArgs[arg] = parsedCArgs[arg]
end
else
modified = true
for arg in pairs( group ) do
newCArgs[arg] = p.extractRelevantFrames( relevantFrameNums, parsedCArgs[arg] )
end
end
end
end
-- Convert arguments back to shapeless format if they were originally
if tArgs[1] then
local i = 1
for argNum = 1, 9 do
tArgs[argNum] = nil
local cArg = newCArgs[argNum]
if cArg then
tArgs[i] = cArg
i = i + 1
end
end
else
for i, arg in pairs( crafting.cArgVals ) do
tArgs[arg] = newCArgs[i]
end
end
tArgs.Output = newCArgs.Output
tArgs.parsed = true
-- Let Module:Recipe table generate these
-- with the modified crafting args
if modified then
tArgs.name = nil
tArgs.ingredients = nil
end
return tArgs
end
--[[Works out which frame is the first frame, and returns its
name, or alias name, for sorting purposes
--]]
function p.getFirstFrameName( frames, subframe )
local frame = frames[1]
if not subframe and frame[1] then
return p.getFirstFrameName( frame[1], true )
end
local alias = frames.aliasReference and frames.aliasReference[1]
return alias and alias.frame.name or frame.name
end
--[[Performs the DPL query which retrieves the arguments from the crafting
templates on the pages within the requested categories.
If more than four categories are given, break them down into batches of four.
--]]
local function dplQueryWrapper( category, ignore )
local data = {}
if type(category) == 'string' then
category = mw.text.split(category, '|')
else
assert(type(category) == 'table')
end
local includeStr = '{' .. i18n.templateCrafting .. '}:' .. table.concat( argList, ':' )
local j = 1
local count = #category
local catParts = text.split( i18n.queryCategory, '%$1' )
for i = 1, count, 4 do
local catSlice = table.concat(category, '|', i, math.min(i + 3, count))
data[j] = mw.getCurrentFrame():callParserFunction( '#dpl:', {
category = catSlice,
nottitleregexp = ignore,
include = includeStr,
mode = 'userformat',
secseparators = '====',
multisecseparators = '===='
})
j = j + 1
end
return table.concat(data)
end
--[[The main body, which retrieves the data, and returns the relevant
crafting templates, sorted alphabetically
--]]
function p.dpl( f )
local args = f
if f == mw.getCurrentFrame() then
args = f:getParent().args
else
f = mw.getCurrentFrame()
end
local ingredients = args[1] and text.split( args[1], '%s*,%s*' ) or { mw.title.getCurrentTitle().text }
local matchTypes = args.match and args.match:find( ',' ) and text.split( args.match, '%s*,%s*' ) or args.match
local ingredientPatterns = createIngredientPatterns( ingredients, matchTypes )
local data
if args.category then
data = dplQueryWrapper( args.category, args.ignore )
else
-- Need to format the catparts
local catParts = text.split( i18n.queryCategory, '%$1' )
local cats = map(ingredients, function (s)
return catParts[1] .. s .. catParts[2]
end)
data = dplQueryWrapper( cats, args.ignore )
end
local showDescription
local templates = {}
local i = 1
for templateArgs in text.gsplit( data:sub( 5 ), '====' ) do
local tArgs = extractArgs( templateArgs )
local newArgs = tArgs and p.processTemplate( tArgs, ingredientPatterns )
if newArgs then
if tArgs.description then
showDescription = '1'
end
templates[i] = {
args = newArgs,
sortKey = mw.ustring.lower(
( newArgs.name or p.getFirstFrameName( newArgs.Output ) )
:gsub( '^' .. prefixes.any .. ' ', '' )
:gsub( '^' .. prefixes.matching .. ' ', '' )
:gsub( '^%[%[', '' )
:gsub( '^[^|]+|', '' )
),
}
i = i + 1
end
end
local templateCount = #templates
if templateCount == 0 then
return '[[Category:' .. i18n.emptyCategory .. ']]'
end
table.sort( templates, function( a, b )
return a.sortKey < b.sortKey
end )
local initialArgs = templates[1].args
initialArgs.head = '1'
initialArgs.showname = '1'
initialArgs.showdescription = showDescription
if not args.continue then
templates[templateCount].args.foot = '1'
end
local out = {}
for i, template in ipairs( templates ) do
out[i] = ( '<!-- [[' .. template.args['%PAGE%'] .. ']] -->\n'
.. crafting.table( template.args ) )
end
return table.concat( out, '\n' )
end
return p