模块:Sandbox/Star00/LootChest

来自Minecraft Wiki
跳转至: 导航搜索
Java bedrock
bastion bastion_bridge
bastion_hoglin_stable
bastion_other
bastion_treasure buriedtreasure
jungle jungle_temple jungle_temple
jungle_temple_dispenser dispenser_trap
shipwreck shipwreck_supply shipwrecksupply
shipwreck_treasure shipwrecktreasure
stronghold stronghold_corridor stronghold_corridor
stronghold_crossing stronghold_crossing
stronghold_library stronghold_library
underwater underwater_ruin_big underwater_ruin_big
underwater_ruin_small underwater_ruin_small
village village_armorer village_armorer
village_butcher village_butcher
village_blacksmith
village_cartographer village_cartographer
village_desert_house village_desert_house
village_fisher
village_fletcher village_fletcher
village_mason village_mason
village_plains_house village_plains_house
village_savanna_house village_savanna_house
village_shepherd village_shepherd
village_snowy_house village_snowy_house
village_taiga_house village_taiga_house
village_tannery village_tannery
village_temple village_temple
village_toolsmith village_toolsmith
village_two_room_house
village_weaponsmith village_weaponsmith
other abandoned_mineshaft abandoned_mineshaft
buried_treasure
desert_pyramid desert_pyramid
end_city_treasure end_city_treasure
igloo_chest igloo_chest
nether_bridge nether_bridge
pillager_outpost pillager_outpost
ruined_portal
shipwreck_map shipwreck
spawn_bonus_chest spawn_bonus_chest
woodland_mansion woodland_mansion
simple_dungeon simple_dungeon
monster_room
local getArgs = require('Module:Arguments').getArgs
local config = require('Module:LootChest/config')


local p = {}

local function makeInvokeFunc(funcName)
  return function (frame)
    local args = getArgs(frame)
    return p[funcName](args)
  end
end

function getAllStru()
  --把全部结构伪装args实现全部表格。
  local args={}
  local text=config['json']['java']
  for stru in text:gmatch('"([^%s]*)":%[') do
    args[#args + 1] = gsub(stru,' ', '_')
  end
  return args
end


function chanceCount(weightProportion,rolls)
  if type(rolls)=="table"
    then
      local fp=1-weightProportion--failureProbability
      local sum=0
      for i=rolls[1],rolls[2] do
        sum=sum+math.pow(fp,i)
      end
      return string.format("%.4f",1-(sum/(rolls[2]-rolls[1]+1)))
    else
      return string.format("%.4f",1-math.pow((1-weightProportion),rolls))
    end
end

function getData(lootTable)

  --通过函数闭包使JSON文件不被刷新。
  return function(name,stru,poolNum,itemNum)
  --利用表结构和匿名函数实现switch。
  local switch = {
      ["value"] = function(stru,poolNum,itemNum)
          if not(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['type']=="minecraft:item") or not(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['type']=="minecraft:item")
             or not(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions']) or not(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions'][1]['count'])
          then
            return 1
          end

          if type(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions'][1]['count'])=='table'
          then
            return tostring(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions'][1]['count']['min'])..
                    '-'..tostring(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions'][1]['count']['max'])
          else
            return lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions'][1]['count']
          end

      end,
      ["averageValue"] = function()
          if not(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['type']=="minecraft:item") or not(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['type']=="minecraft:item")
             or not(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions']) or not(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions'][1]['count'])
          then
            return 1
          end

          if type(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions'][1]['count'])=='table'
          then
            return (lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions'][1]['count']['min']+lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions'][1]['count']['max'])/2
          else
            return lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions'][1]['count']
          end
        end,
      ["weight"] = function()
          return lootTable[stru]['pools'][poolNum]['entries'][itemNum]['weight']
      end,
      ["name"] = function()
          if not(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['type']=="minecraft:item" or lootTable[stru]['pools'][poolNum]['entries'][itemNum]['type']=="item")
          then
            return "Nothing"
          end

          local name=lootTable[stru]['pools'][poolNum]['entries'][itemNum]['name']

          if lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions']
          then
            for e,r in ipairs(lootTable[stru]['pools'][poolNum]['entries'][itemNum]['functions']) do
              if r['function']=='minecraft:set_damage'
              then
                name=name..'/set_damage:'..string.format("%.2f", r['damage']['min'])..'-'..string.format("%.2f", r['damage']['max'])
              end
              
              if r['function']=='minecraft:enchant_randomly'
              then
                name=name..'/enchant_randomly'
              end
            end
          end

          return name
      end,
      --计算用的堆叠数
      ["rolls"] = function()
          if type(lootTable[stru]['pools'][poolNum]['rolls'])=="table" then
            return {
            lootTable[stru]['pools'][poolNum]['rolls']['min'],
            lootTable[stru]['pools'][poolNum]['rolls']['max']
            }
          else
            return lootTable[stru]['pools'][poolNum]['rolls']
          end
      end,
      --显示用的堆叠数
      ["rollsOut"] = function()
          if type(lootTable[stru]['pools'][poolNum]['rolls'])=="table" then
            return (lootTable[stru]['pools'][poolNum]['rolls']['min']..'-'..lootTable[stru]['pools'][poolNum]['rolls']['max'])..'x'
          else
            return lootTable[stru]['pools'][poolNum]['rolls']
          end
      end,
      ["entries"] = function()
          return lootTable[stru]['pools'][poolNum]['entries']--【itemNum】,将被遍历
      end,
      ["pools"] = function()
          return lootTable[stru]['pools']--【poolNum】,将被遍历
      end,
      ["table"] = function()
          return lootTable
      end
     
    }
    
    return switch[name](stru,poolNum,itemNum)
  end
end

function dataParsing(args,edition,genre)
  local data=getData(config['json'][edition])
  --此处data被赋予一个函数,作为数据查找函数。
  local poolsList,itemNum,poorsWeight,rolls,fakeItemNum,stru
  local struList,resultList,poolsList,poorsValue={}
  local listNum=1

  local loopPrimer
  if genre=="all" then loopPrimer=data('table') else loopPrimer=args end

  local stru
  for q,w in pairs(loopPrimer) do
    --结构循环
    resultList,poorsValue={},{}

    if genre=="all" then stru=q else stru=w end

    if data('table')[stru]~=nil 
    then
      itemNum=1
      --贯穿奖池循环和物品循环的物品序号。

      poolsList={}

      for o in ipairs(data('pools',stru)) do
        --奖池循环

        poorsWeight=0
        rolls=data('rolls',stru,o)

        if type(rolls)=='table'
          then
            poorsValue[o]=rolls[1]..'-'..rolls[2]
          else
            poorsValue[o]=rolls
        end

        fakeItemNum=itemNum
        --伪物品序号,服务于第二个物品循环,用于重新遍历第一个循环的物品,计算其概率等信息。

        for n in ipairs(data('entries',stru,o)) do
          --物品循环
          poolsList[itemNum]={}
          poolsList[itemNum]['name']=data('name',stru,o,n)
          poolsList[itemNum]['value']=data('value',stru,o,n)
          poolsList[itemNum]['pools']=o

          if data('weight',stru,o,n) then
            poolsList[itemNum]['weight']=data('weight',stru,o,n)
          else
            poolsList[itemNum]['weight']=1
          end

          poolsList[itemNum]['averageValue']=data('averageValue',stru,o,n)
          poorsWeight=poorsWeight+poolsList[itemNum]['weight']
          itemNum=itemNum+1
        end
        --到这里为止,poolsList包含了一个奖池的全部信息,然后在下一个循环进行几率等内容的计算,之后在最外层进行排序。

        for n in ipairs(data('entries',stru,o)) do
          --物品循环
          poolsList[fakeItemNum]['weightProportion']=tonumber(poolsList[fakeItemNum]['weight'])/poorsWeight
          poolsList[fakeItemNum]['weightProportionOut']='<sup>'..tostring(poolsList[fakeItemNum]['weight'])..'</sup>/<sub>'..tostring(poorsWeight)..'</sub>'
          poolsList[fakeItemNum]['chance']=chanceCount(poolsList[fakeItemNum]['weightProportion'],rolls)
          poolsList[fakeItemNum]['chanceOut']=tonumber(poolsList[fakeItemNum]['chance']*100)..'%'
          poolsList[fakeItemNum]['itemNum']=string.format("%.2f",poolsList[fakeItemNum]['averageValue']*poolsList[fakeItemNum]['chance'])
          poolsList[fakeItemNum]['boxNum']=string.format("%.1f",1/poolsList[fakeItemNum]['chance'])
          fakeItemNum=fakeItemNum+1
        end

        table.sort( poolsList , function(a,b)
          return a['chance'] > b['chance']
        end )

      end
      struList[listNum]={}
      struList[listNum]['name']=stru
      struList[listNum]['value']=poolsList
      struList[listNum]['poolsValue']=poorsValue
      struList[listNum]['poolNum']=#data('pools',stru)
      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)
  --获取all函数的结果文本。
  local wikiTable,poolNum,wikiTablePart='','',{}
  local box=mw.html.create("div")
  box:cssText('display:flex;flex-wrap:wrap')
  
  local itemNumMax=0
  for y,u in ipairs(data) do
    if u['itemNum']>itemNumMax
      then
        itemNumMax=u['itemNum']
    end
  end

  local fill
  for i,k in ipairs(data) do
    if k['poolNum']~=0
    then
      poolNum=k['poolNum']
      fill=""
      for h=1,itemNumMax-k['itemNum'] do
       fill=fill..'| class="talkpage-topic-list-author" colspan='..(poolNum*2+4)..' |<sup>0</sup>/<sub>0</sub>\n|-\n'
       --填充高度的空表,如要调整值需要注意高度。
       --此处临时借用topic list的样式,全部完成时需整理
      end
      --表头部分
      wikiTable='{| class="wikitable sortable jquery-tablesorter" style="'..config['style']['allTableStyle']..'"\n!colspan="'..(poolNum*2+4)..'"|'..config['struLink'](k['name'])..'\n|-\n'
      --此处

      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
        --值循环
        wikiTablePart[o]='|'..config['itemLink'](p['name'],config)

        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
      --if itemNumMax>k['itemNum']
      --  then
      --    wikiTable=wikiTable..fill
      --end
      wikiTable=wikiTable..'|}'
      box:wikitext('<div>\n'..wikiTable..'\n</div>')
    end
  end
  return tostring(box)
end

function itemDataCov(args)
  local itemList={}
  local boxNum
  local data=dataParsing({},'java','all')
  for argNum,name in ipairs(args) do
    boxNum=1
    itemList[argNum]={}
    itemList[argNum]['name']=name
    itemList[argNum]['list']={}
    for struNum,struInf in pairs(data) do

      for itemNum,itemInf in ipairs(struInf['value']) do

        if itemInf['name']:gsub('minecraft:', '')==name
        then

          itemList[argNum]['list'][boxNum]=itemInf
          itemList[argNum]['list'][boxNum]['stru']=struInf['name']
          boxNum=boxNum+1

        end

      end

    end
  itemList[argNum]['long']=#itemList[argNum]['list']

  end

  return itemList

end

function getTableItem(data)
  local wikiTable='{| class="wikitable sortable jquery-tablesorter" style="'..config['style']['itemTableStyle']..'"\n'
                    ..'! 物品 \n! 结构 \n! 容器类型 \n! 数量 \n! 几率\n|-\n'

  for itemNum,itemInf in ipairs(data) do
    wikiTable=wikiTable..'| rowspan='..itemInf['long']..'|'..itemInf['name']..'\n'
  end

  wikiTable=wikiTable..'|}'

  return wikiTable
end

p.all = makeInvokeFunc('_all')

function p._all(args)
  local dataJava,dataBedrock,dataJavaDev,dataBedrockBeta
  dataJava=dataParsing(args,'java','arg')
  dataBedrock=dataParsing(args,'bedrock','arg')
  if config['debug']['only bedrock'] then return getTableAll(dataBedrock) end
  if config['debug']['only java'] then return getTableAll(dataJava) end
  if dataJava==dataBedrock
  then
    return '[[Java版]]与[[基岩版]]:\n'..getTableAll(dataJava)
  else
    return '[[Java版]]:\n'..getTableAll(dataJava)..'[[基岩版]]:\n'..getTableAll(dataBedrock)
  end

end

p.item = makeInvokeFunc('_item')

function p._item(args)
  return getTableItem(itemDataCov(args))

end

return p