Module:Sandbox/LootChest
Jump to navigation
Jump to search
Usage[edit source]
[view] [edit] [history] [refresh]The above documentation is transcluded from Module:Sandbox/LootChest/doc.
local getArgs = require('Module:Arguments').getArgs
local config = require('Module:Sandbox/LootChest/config')
local cov = config['json']['cov']
local sprite, spriteFile, alink
if not(config['customize']['itemLink'] and config['customize']['struLink'])
then
sprite = require('Module:Sprite').link
spriteFile = require('Module:SpriteFile').link
end
if config['customize']['noUseAutoLink'] == true
then
alink = function(a) return a end
else
alink = require('Module:Autolink').invlink
end
local p = {}
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame)
return p[funcName](args)
end
end
function struLink(name)
-- 输入结构的ID,返回最后结果。
local text = name
if cov['structure']['text'][name]
then
text = cov['structure']['text'][name]
end
local id = ''
if cov['structure']['sprite-id'][name]
then
id = cov['structure']['sprite-id'][name]
end
local dataType
if cov['structure']['sprite-data-type'][name]
then
dataType = cov['structure']['sprite-data-type'][name]
else
dataType = cov['structure']['sprite-data-type']['default']
end
local link = 'none'
if text:find('%|')
then
link = text:match('%[%[(.*)%|')
text = text:match('%|(.*)%]%]')
end
return spriteFile({['name'] = dataType, ['id'] = id, ['link'] = link, ['text'] = text})
end
function ref(list)
-- 输入物品的命名空间ID和itemLink最后的显示结果,对齐检索cov.json并添加注释。
local ref = ""
local generator = function(text, name)
return mw.getCurrentFrame():callParserFunction('#tag:ref', {
text,
['name'] = name,
['group'] = '战利品',
})
end
for _, entry in ipairs(list)
do
ref = ref..generator(entry[1], entry[2])
end
return ref
end
function itemLink(NsId, aux, functions, ref)
-- 输入物品的命名空间ID,返回最终的显示结果。
local enName, id, link, text, dataType
local refText = {}
enName = NsId:gsub('_', ' ')
--- 如果在cov.json中存在转换规则,则进行转换,否则直接将命名空间ID作为英文名输入sprite
local itemCov = {}
if cov['item']['cov'][NsId]
then
itemCov = cov['item']['cov'][NsId]
if aux and itemCov['aux']
then
itemCov = itemCov['aux'][tonumber(aux)] or itemCov
end
if itemCov['name'] then enName = itemCov['name'] end
if itemCov['id'] then id = itemCov['id'] end
if itemCov['link'] then link = itemCov['link'] end
if itemCov['text'] then text = itemCov['text'] end
end
local Er, Sd, dataNum
local funcCov
for _, func in ipairs(functions) do
funcCov = itemCov['functions']
if funcCov and funcCov[func['function']] and funcCov[func['function']][tonumber(func['value']) or func['value']]
then
funcCov = funcCov[func['function']][tonumber(func['value']) or func['value']]
if funcCov['name'] then enName = funcCov['name'] end
if funcCov['id'] then id = funcCov['id'] end
if funcCov['link'] then link = funcCov['link'] end
if funcCov['text'] then text = funcCov['text'] end
end
Er = Er or func['function'] == 'enchant_randomly' or func['function'] == 'enchant_with_levels' or func['function'] == 'specific_enchants' or func['function'] == 'enchant_book_for_trading' or func['function'] == 'set_enchantments'
Sd = Sd or func['function'] == 'set_damage'
end
text = text or alink(enName):gsub('.*%|', '')
if Er and Sd and config['mark']['damaged enchanted']
then
text = config['mark']['damaged enchanted']:gsub('$s',text)
else
if Er then text = config['mark']['enchanted']:gsub('$s',text) end
if Sd then text = config['mark']['damaged']:gsub('$s',text) end
end
dataType = cov['item']['sprite-data-type'][NsId] or cov['item']['sprite-data-type']['default']
for _, entry in ipairs(ref)
do
table.insert(refText, entry[2])
end
table.sort(refText)
return {['name'] = dataType, [1] = enName, ['id'] = id, ['link'] = link, ['text'] = text}, text .. table.concat(refText, ', ')
end
function chanceCount(weightProportion, rolls)
-- 概率计算函数
if type(rolls) == "table"
then
local fp = 1 - weightProportion--failureProbability
local sum = 0
for i = rolls['min'], rolls['max'] do
sum = sum + math.pow(fp, i)
end
return string.format("%.4f", 1 - (sum / (rolls['max'] - rolls['min'] + 1)))
else
return string.format("%.4f", 1 - math.pow((1 - weightProportion), rolls))
end
end
function getItemStack(item, poolFuncs, edition)
local functions = item['functions'] or {}
for _,v in ipairs(poolFuncs) do table.insert(functions,v) end
local covSingle, funcName, funcValue
local id = (item['name'] or 'nothing'):gsub('minecraft:', '')
local aux = 0
local funcList = {}
local count, averageCount = 1, 1
local ref = {}
local checkAssign = true
---遍历所有函数
for _, func in pairs(functions) do
funcName = func['function']:gsub('minecraft:','')
funcValue = funcName
if funcName == 'set_count'
then
count = func['count']
elseif funcName =='set_data'
then
aux = func['data']
elseif funcName =='exploration_map' and id == 'map'
then
id = 'buried_treasure_map'--此处使用英文名而非nsid以作区分
else
covSingle = config['function'][funcName]
if covSingle
then
---处理函数值
if covSingle[1]
then
if type(func[covSingle[1]]) == 'table'
then
if func[covSingle[1]]['min'] --For JE/BE enchant_with_levels
then funcValue = tostring(func[covSingle[1]]['min']) .. '-'..tostring(func[covSingle[1]]['max'])
elseif func[covSingle[1]][1] and type(func[covSingle[1]][1]) == 'table'
then --For BE specific_enchants & BE enchant_book_for_trading & JE/BE set_stew_effect
local last
for _, v in ipairs(func[covSingle[1]]) do last = v end
funcValue = tostring(last['id'] or last['type'] or last['name']):gsub('minecraft:','')
checkAssign = false
else
if funcName == 'set_enchantments'
then
local geusage
for _, v in pairs(func[covSingle[1]]) do geusage = _ end
funcValue = tostring(geusage):gsub('minecraft:','')..'-'..tostring(func[covSingle[1]][geusage]) --For JE set_enchantments
checkAssign = false
else
funcValue = tostring(func[covSingle[1]][1]):gsub('minecraft:','') --For JE enchant_randomly
end
end
else
funcValue = tostring(func[covSingle[1]]):gsub('minecraft:','')
end
end
---储存各个函数
table.insert(
funcList,
{['function'] = funcName,
['value'] = funcValue})
--处理注释
local funcRefList = cov['note']['functions']
if funcRefList[funcName] and funcRefList[funcName][tonumber(funcValue) or funcValue]
then
table.insert(ref, {funcRefList[funcName][tonumber(funcValue) or funcValue],
covSingle['name'] or funcName .. ':'..((config['function'][funcValue] or {})['name'] or funcValue)})
end
end
end
end
---处理物品数量
if type(count) == 'table'
then
if count['max'] ~= count['min']
then
averageCount = (count['min'] + count['max']) /2
count = tostring(count['min']) ..
'-'..tostring(count['max'])
else
averageCount = count['min']
count = tostring(count['min'])
end
else
averageCount = count
count = tostring(count)
end
--此处使用硬编码以区分游戏中做特殊处理的物品
if id == 'book' and funcList[1] and funcList[1]['function']:match('enchant')
then id = 'enchanted_book'
elseif id == 'map' and edition:find('java')
then id = 'empty_map'--此处使用英文名而非nsid以作区分
end
--处理注释
if cov['note']['assign'][id] and checkAssign
then
table.insert(ref, {cov['note']['assign'][id], id})
end
return {
['id'] = id,
["value"] = count,
["averageValue"] = averageCount,
["weight"] = item['weight'] or 1,
['functions'] = funcList,
["aux"] = tostring(aux),
['ref'] = ref
}
end
function dataParsing(args, edition, genre)
-- 获取数据table,同时用于all模式和item模式。
local loot = config['json'][edition]
local struList, listNum = {}, 1
local poorsValue, stru, itemNum, rItemNum, poolsList, poolNum
local poorsWeight, rolls
-- 预定义循环内变量,分别为函数体内使用,第一层for使用,第二层for使用
if genre == "all" then loopPrimer = loot else loopPrimer = args end
for q, w in pairs(loopPrimer) do
--结构循环
itemNum, rItemNum = 1, 1
poolsList, poorsValue = {}, {}
if genre == "all" then stru = q else stru = w end
if loot[stru] ~= nil
then
for o, pool in ipairs(loot[stru]['pools']) do
--奖池循环
poorsWeight = 0
rolls = pool['rolls']
if type(rolls) == 'table'
then
poorsValue[o] = rolls['min'] .. '-'..rolls['max']
else
poorsValue[o] = tostring(rolls)
end
for _, itemStack in ipairs(pool['entries']) do
--物品循环
poolsList[itemNum] = getItemStack(itemStack, pool['functions'] or {}, edition)
poolsList[itemNum]['pools'] = o
poorsWeight = poorsWeight + poolsList[itemNum]['weight']
itemNum = itemNum + 1
end
--到这里为止,poolsList包含了一个奖池的全部信息,然后在下一个循环进行概率等内容的计算,之后在最外层进行排序。
for n in ipairs(pool['entries']) do
--物品循环
poolsList[rItemNum]['weightProportion'] = tonumber(poolsList[rItemNum]['weight']) / poorsWeight
poolsList[rItemNum]['weightProportionOut'] = '<sup>'..tostring(poolsList[rItemNum]['weight']) .. '</sup>/<sub>'..tostring(poorsWeight) .. '</sub>'
poolsList[rItemNum]['chance'] = chanceCount(poolsList[rItemNum]['weightProportion'], rolls)
poolsList[rItemNum]['chanceOut'] = tonumber(poolsList[rItemNum]['chance'] * 100) .. '%'
poolsList[rItemNum]['itemNum'] = string.format("%.2f", poolsList[rItemNum]['averageValue'] * poolsList[rItemNum]['chance'])
poolsList[rItemNum]['boxNum'] = string.format("%.1f", 1 / poolsList[rItemNum]['chance'])
rItemNum = rItemNum + 1
end
table.sort(poolsList, function(a, b) return a['chance'] > b['chance'] end)
poolNum = o
end
struList[listNum] = {}
struList[listNum]['name'] = stru
struList[listNum]['value'] = poolsList
struList[listNum]['poolsValue'] = poorsValue
struList[listNum]['poolNum'] = poolNum
struList[listNum]['itemNum'] = itemNum - 1
listNum = listNum + 1
else
struList[listNum] = {}
struList[listNum]['poolNum'] = 0
struList[listNum]['itemNum'] = 0
listNum = listNum + 1
end
end
table.sort(struList, function(a, b) return a['itemNum'] > b['itemNum'] end)
return struList
end
function getTableAll(data, args)
--获取all函数的结果文本。
local wikiTable, poolNum, wikiTablePart = '', '', {}
for i, k in ipairs(data) do
if k['poolNum'] ~= 0
then
poolNum = k['poolNum']
--表头部分
wikiTable = wikiTable..'<div>\n{| class="wikitable sortable jquery-tablesorter" style="'..config['style']['allTableStyle'] .. '"\n!colspan="' .. (poolNum * 2 + 4)
if args['header'] then
wikiTable = wikiTable..'"|'.. args['header'] .. '\n|-\n'
elseif config['customize']['struLink'] then
wikiTable = wikiTable..'"|'..config['struLink'](k['name']) .. '\n|-\n'
else
wikiTable = wikiTable..'"|'..struLink(k['name']) .. '\n|-\n'
end
--此处
wikiTable = wikiTable..
'! rowspan=2 | ' .. config['header']['item'] .. '\n' ..
'! colspan='..poolNum..' | ' .. config['header']['stack'] .. '\n' ..
'! colspan='..poolNum..' | ' .. config['header']['weight'] .. '\n' ..
'! rowspan=2 | ' .. config['header']['probability'] .. '\n' ..
'! rowspan=2 | ' .. config['header']['itemNumber'] .. '\n' ..
'! rowspan=2 | ' .. config['header']['boxNumber'] .. '\n |- \n'
--表中部分
for h = 1, 2 do
for y = 1, poolNum do
wikiTable = wikiTable..'! '..config['header']['weightNoteH']..k['poolsValue'][y]..config['header']['weightNoteF']..k['poolsValue'][y] .. '×</abbr> \n'
end
end
wikiTable = wikiTable..'|- \n'
for o, p in ipairs(data[i]['value']) do
--值循环
if config['customize']['itemLink'] then
wikiTablePart[o] = '|'..config['itemLink'](p['id'], p['aux'], p['functions'], config)..ref(p["ref"])
else
wikiTablePart[o] = '|'..spriteFile(itemLink(p['id'], p['aux'], p['functions'], p['ref']))..ref(p["ref"])
end
for m = 1, poolNum do
if p['pools'] == m
then
wikiTablePart[o] = wikiTablePart[o] .. '||'..p['value']
else
wikiTablePart[o] = wikiTablePart[o] .. '||' .. ' '
end
end
for m = 1, poolNum do
if p['pools'] == m
then
wikiTablePart[o] = wikiTablePart[o] .. '||'..p['weightProportionOut']
else
wikiTablePart[o] = wikiTablePart[o] .. '||' .. ' '
end
end
wikiTablePart[o] = wikiTablePart[o] .. '||'..p['chanceOut'] .. '||'..p['itemNum'] .. '||'..p['boxNum'] .. '\n|-\n'
wikiTable = wikiTable..wikiTablePart[o]
end
wikiTable = wikiTable..'|}\n</div>'
end
end
return wikiTable
end
function itemDataCov(args, edition)
local itemList = {}
local link,key,aux,name
local data = dataParsing({}, edition, 'all')
for _, arg in ipairs(args) do
name = arg:gsub('minecraft:', ''):gsub(':.*','')
aux = arg:gsub('minecraft:', ''):match(':(.*)')
for _, struInf in ipairs(data) do
for _, itemInf in ipairs(struInf['value']) do
if itemInf['id'] == name and (aux==nil or itemInf['aux'] == aux)
then
link, key = itemLink(itemInf['id'], itemInf['aux'], itemInf['functions'], itemInf['ref'])
itemList[key] = itemList[key] or {}
itemList[key]['ref'] = itemList[key]['ref'] or ref(itemInf["ref"])
itemList[key]['link'] = itemList[key]['link'] or spriteFile(link)
itemList[key]['list'] = itemList[key]['list'] or {}
itemInf['stru'] = struInf['name']
table.insert(itemList[key]['list'], itemInf)
end
end
end
end
return itemList
end
function getTableItem(data)
local wikiTable = ''
if next(data) ~= nil then
wikiTable = '\n{| class="wikitable sortable jquery-tablesorter" style="'..config['style']['itemTableStyle'] .. '\n' ..
'! ' .. config['header']['item'] .. '\n' ..
'! ' .. config['header']['source'] .. '\n' ..
'! ' .. config['header']['itemNumber'] .. '\n' ..
'! ' .. config['header']['quantity'] .. '\n' ..
'! ' .. config['header']['probability'] .. '\n' ..
'! ' .. config['header']['boxNumber'] .. '\n' ..
'|-\n'
for _, itemInf in pairs(data) do
if itemInf['list'][1]
then
wikiTable = wikiTable..'| rowspan='.. #itemInf['list'] .. '|'.. itemInf['link'] .. itemInf['ref'] .. '\n'
for _, lineInf in pairs(itemInf['list']) do
wikiTable = wikiTable
.. '|' ..struLink(lineInf['stru']) .. '\n'
.. '|' ..lineInf['itemNum'] .. '\n'
.. '|' ..lineInf['value'] .. '\n'
.. '|' ..lineInf['chanceOut'] .. '\n'
.. '|' ..lineInf['boxNum'] .. '\n'
.. '|-\n'
end
end
end
wikiTable = wikiTable..'|}\n'
end
return wikiTable
end
function getTableItemAll(edition)
local data = dataParsing({}, edition, 'all')
local itemList, resultList = {}, {}
for struNum, struInf in pairs(data) do
for itemNum, itemInf in ipairs(struInf['value']) do
itemList[itemInf['id']] = true
end
end
for id in pairs(itemList) do
table.insert(resultList, id)
end
resultList['version'] = edition
return p._item(resultList)
end
function result(args, getData, getTable)
local genre
if args['type'] == 'all' or args[1] == 'all'
then
genre = 'all'
else
genre = 'arg'
end
local toText = function (dt)
local text = mw.html.create("div"):addClass('loot-chest-container'):wikitext(dt)
-- return require( 'Module:TSLoader' ).call( 'User:Star00/LootChest/styles.css' ) .. tostring(text)
return tostring(text)
end
if args['version']
then return toText(getTable(getData(args, args['version'], genre), args))
end
local cout = ''
local dataJava, dataBedrock, dataJavaDev, dataBedrockBeta
dataJava = getTable(getData(args, 'java', genre), args)
dataBedrock = getTable(getData(args, 'bedrock', genre), args)
if config['debug']['onlyJava'] or args['only'] == 'java'
then
cout = toText(dataJava)
elseif config['debug']['onlyBedrock'] or args['only'] == 'bedrock'
then
cout = toText(dataBedrock)
elseif mw.text.killMarkers(dataJava) == mw.text.killMarkers(dataBedrock)
then
cout = config['label']['javaAndBedrock'] .. '\n'..toText(dataJava)
else
if dataJava ~= ''
then
cout = config['label']['java'] .. '\n'..toText(dataJava)
end
if dataBedrock ~= ''
then
cout = cout .. config['label']['bedrock'] .. '\n'..toText(dataBedrock)
end
end
if config['switch']['javaDev'] and args['only'] ~= 'bedrock'
then
dataJavaDev = getTable(getData(args, 'javaDev', genre), args)
if mw.text.killMarkers(dataJava) ~= mw.text.killMarkers(dataJavaDev) and dataJavaDev ~= ''
then
cout = cout .. config['label']['javaDev'] .. '\n'..toText(dataJavaDev)
end
end
if config['switch']['bedrockBeta'] and args['only'] ~= 'java'
then
dataBedrockBeta = getTable(getData(args, 'bedrockBeta', genre), args)
if mw.text.killMarkers(dataBedrock) ~= mw.text.killMarkers(dataBedrockBeta) and dataBedrockBeta ~= ''
then
cout = cout .. config['label']['bedrockBeta'] .. '\n'..toText(dataBedrockBeta)
end
end
return cout
end
p.all = makeInvokeFunc('_all')
function p._all(args)
return result(args, dataParsing, getTableAll)
end
p.item = makeInvokeFunc('_item')
function p._item(args)
if args['type'] == 'all' or args[1] == 'all'
then
return result(args, function(a,b) return b end, getTableItemAll)
else
return result(args, itemDataCov, getTableItem)
end
end
return p