Minecraft Wiki
Advertisement
local p = {}

local breakingTimeHeader;
local function getBreakingTimeHeader( f )
    if breakingTimeHeader == nil then
        breakingTimeHeader = 'Время [[Добывание|разрушения]]' .. f:preprocess( '<ref group="FN" name="breakingtimenote">Время для незачарованных инструментов, используемых игроком без наложенных эффектов, в секундах. Для большей информации см. [[Добывание#Скорость|Добывание § Скорость]].</ref>' )
    end
    return breakingTimeHeader
end

function p.row( f )
    local args = require( [[Модуль:ProcessArgs]] ).norm()
    local sprite = require( [[Модуль:Спрайт]] )

    local function getDplVar( var )
        local val = f:callParserFunction( '#dplvar', 'breaking ' .. var )
        if val == '' then
            val = false
        end
        return val
    end
    local dplVars = {}
    local function setDplVar( var, val )
        table.insert( dplVars, 'breaking ' .. var )
        table.insert( dplVars, val or '1' )
    end

    local rows = {}
    local tableParts = {}
    local categories = {}

    local horizontal
    args[1] = args[1] or '' -- чтобы не переделывать весь модуль, ранее считавший, что тут строка
    
    -- Подставляет название страницы, если параметр args[1] не указан.
    if (args[1] == '') or (args[1] == nil) then
		args[1] = mw.title.getCurrentTitle().text
		args["встолбик"] = 1
	end
	
    if args["встолбик"] or args[1]:match( ';' ) then
        horizontal = true
    end
    local showTool = true
    local showShears = true
    local showSword = true
    local header, sortable, simple
    if horizontal or not getDplVar( 'header' ) then
        if args["скрытьинструмент"] or horizontal and ( not args[2] or args[2]:lower() == 'any' or args[2]:lower() == 'none' ) then
            showTool = false
            setDplVar( 'hidetool' )
            breakingTimeHeader = 'Время [[Добывание|разрушения]]'
        end
        if args["скрытьножницы"] or horizontal and not args["ножницы"] then
            showShears = false
            setDplVar( 'hideshears' )
        end
        if args["скрытьмеч"] or horizontal and not args["меч"] then
            showSword = false
            setDplVar( 'hidesword' )
        end

        sortable = not horizontal and args["сортировка"]
        if sortable then
            setDplVar( 'sortable' )
        end
        simple = args["простой"]
        if simple and not horizontal then
            setDplVar( 'simple' )
        end

        local tableClasses = { 'wikitable' }
        if sortable then
            table.insert( tableClasses, 'sortable' )
        end
        table.insert( rows, ' {| class="' .. table.concat( tableClasses, ' ' ) .. '" style="text-align:center"' )

        local sortType = ''
        if sortable then
            sortType = 'data-sort-type="number"'
        end
        local rowspan = ''
        if not horizontal then
            rowspan = 'rowspan="2" '
        end
        header = {
            '! ' .. rowspan .. ' | Блок'
        }

        if not simple then
            table.insert( header, '! ' .. rowspan .. sortType .. ' | Прочность' )
            if showTool then
                table.insert( header, '! ' .. rowspan .. ' | Инструмент' )
            end
        end

        local toolColumns = {}
        if showTool then
            local firstTool = mw.text.trim( simple and 'Инструмент' or args[2] or 'Любой' ):gsub( '^%l', string.upper )
            firstTool = mw.text.split( firstTool, ';' )[1]
            if firstTool == 'Кирка' or firstTool == 'Лопата' or firstTool == 'Мотыга' then
                toolColumns = { 'Деревянная', 'Каменная', 'Железная', 'Алмазная', 'Незеритовая', 'Золотая' }
            else
                toolColumns = { 'Деревянный', 'Каменный', 'Железный', 'Алмазный', 'Незеритовый', 'Золотой' }
            end
        end
        table.insert( toolColumns, 1, 'По умолчанию' )

        if not simple then
            if showShears then
                table.insert( toolColumns, 'Ножницы' )
            end
            if showSword then
                table.insert( toolColumns, 'Меч' )
            end
        end

        if not horizontal then
            table.insert( header, '! colspan="' .. #toolColumns .. '" |' .. getBreakingTimeHeader( f ) )
            table.insert( header, '|-' )
        end

        local toolSprites = {
            ["Деревянный"] = {'Спрайт/Блок', 'дубовые-доски' },
            ["Деревянная"] = {'Спрайт/Блок', 'дубовые-доски' },
            ["Каменный"] = { 'Спрайт/Блок', 'булыжник' },
            ["Каменная"] = { 'Спрайт/Блок', 'булыжник' },
            ["Железный"] = { 'Спрайт/Предмет', 'железный-слиток' },
            ["Железная"] = { 'Спрайт/Предмет', 'железный-слиток' },
            ["Алмазный"] = { 'Спрайт/Предмет', 'алмаз' },
            ["Алмазная"] = { 'Спрайт/Предмет', 'алмаз' },
            ["Незеритовый"] = { 'Спрайт/Предмет', 'незеритовый-слиток' },
            ["Незеритовая"] = { 'Спрайт/Предмет', 'незеритовый-слиток' },
            ["Золотой"] = { 'Спрайт/Предмет', 'золотой-слиток' },
            ["Золотая"] = { 'Спрайт/Предмет', 'золотой-слиток' },
            ["Ножницы"] = { 'Спрайт/Предмет', 'ножницы' },
            ["Меч"] = { 'Спрайт/Предмет', 'деревянный-меч' }
        }
        for _, tool in ipairs( toolColumns ) do
            if toolSprites[tool] then
                local image, spriteCat = sprite.sprite{
                    ["данные"] = toolSprites[tool][1],
                    toolSprites[tool][2],
                    ["текст"] = tool
                }
                table.insert( header, '! style="text-align:left" ' .. sortType .. ' | ' .. image )
                table.insert( categories, spriteCat )
            else
                table.insert( header, '! ' .. sortType .. ' | ' .. tool )
            end
        end

        if not horizontal then
            header = table.concat( header, '\n' )
            setDplVar( 'header', header )
        end
        table.insert( tableParts, header )
    else
        showTool = not getDplVar( 'hidetool' )
        showShears = not getDplVar( 'hideshears' )
        showSword = not getDplVar( 'hidesword' )
        sortable = getDplVar( 'sortable' )
        simple = getDplVar( 'simple' )
    end

    local hardness = require( [[Модуль:Значения блоков]] ).value

    local function fillCells( cellsTable, text, num )
        for i = 1, num do
            table.insert( cellsTable, text )
        end
    end
    local materialGrade = {
        ["Любой"] = 0, ["Любая"] = 0,
        ["Деревянный"] = 1, ["Деревянная"] = 1,
        ["Золотой"] = 1, ["Золотая"] = 1,
        ["Каменный"] = 2, ["Каменная"] = 2,
        ["Железный"] = 3, ["Железная"] = 3,
        ["Алмазный"] = 4, ["Алмазная"] = 4,
        ["Незеритовый"] = 5, ["Незеритовая"] = 5,
        ["Нет"] = 6
    }
    local materialSpeed = {
        ["Нет"] = 1,
        ["Любой"] = 1, ["Любая"] = 1,
        ["Деревянный"] = 2, ["Деревянная"] = 2,
        ["Каменный"] = 4, ["Каменная"] = 4,
        ["Железный"] = 6, ["Железная"] = 6,
        ["Алмазный"] = 8, ["Алмазная"] = 8,
        ["Незеритовый"] = 9, ["Незеритовая"] = 9,
        ["Золотой"] = 12, ["Золотая"] = 12
    }
    local numberMaterials = 6

    local function insertBlock( blockArgs )
        local cells = {}
        local blocks = mw.text.split( blockArgs[1], '%s*,%s*' )
        local hardnessVal = tonumber( hardness{ blocks[1], ["тип"] = 'прочности' } )
        if not hardnessVal then
            hardnessVal = '?'
            local title = mw.title.getCurrentTitle()
            if title.namespace == 0 and not title.isSubpage then
                table.insert(categories, '[[Категория:Отсутствующие значения прочности]]')
            end
        end
        local unbreakable
        if hardnessVal == -1 or blockArgs.liquid then
            unbreakable = true
        end

        local blockSprites = {}
        local links = mw.text.split( blockArgs["ссылка"] or '', '%s*,%s*' )
        local ids = mw.text.split( blockArgs["спрайт"] or '', '%s*,%s*' )
        local items = mw.text.split( blockArgs["предмет"] or '', '%s*,%s*' )
        for i, block in ipairs( blocks ) do
            local link
            if not links[i] and links[1] ~= '' then
                link = links[1]
            elseif links[i] ~= '' then
                link = links[i]
            end
            local id
            if not ids[i] and ids[1] ~= '' then
                id = ids[1]
            elseif ids[i] ~= '' then
                id = ids[i]
            end
            local blockText
            if args["сократить"] then
                blockText = block:gsub( args["сократить"] .. '$', '' )
            else
                blockText = block
            end
            local blockSpriteArgs = {
                ["данные"] = 'Спрайт/Блок',
                block,
                ["текст"] = blockText,
                ["ссылка"] = link,
                ["ID"] = id
            }
            if items[i] == '1' or not items[i] and items[1] == '1' then
                blockSpriteArgs["данные"] = 'Спрайт/Предмет'
            end

            local image, spriteCat = sprite.link( blockSpriteArgs )
            table.insert( blockSprites, image )
            table.insert( categories, spriteCat )
        end
        table.insert( cells,
            '! style="text-align:left" | ' .. table.concat( blockSprites, '<br>' ) .. ( blockArgs["прим"] or '' )
        )

        local tool = mw.text.trim( simple and 'Инструмент' or blockArgs[2] or 'Любой' ):gsub( '^%l', string.upper )
        local material = mw.text.trim( simple and blockArgs[2] or blockArgs[3] or 'Любой' ):gsub( '^%l', string.upper )
        if tool == 'Нет' then
            material = tool
        end
        if not simple then
            local hardnessText = hardnessVal
            if hardnessVal == -1 then
                hardnessText = ( sortable and 'data-sort-value="999" | ' or '' ) .. '∞'
            end
            table.insert( cells, '|' .. hardnessText )

            if showTool then
                local toolCell = '—'
                if tool ~= 'Любой' and tool ~= 'Нет' then
                    local isMaterialSpecified = (material ~= 'Любой') and (material ~= 'Нет')
                    local toolName = ( isMaterialSpecified and material .. ' ' or '' ) .. tool
                    if toolName == 'Топор' then
                    	wooden = 'Деревянный '
                    else 
                    	wooden = 'Деревянная '
                    end
                    local fullToolName = ( (not isMaterialSpecified) and wooden or '' ) .. toolName
                    local image, spriteCat = sprite.sprite{
                        ["данные"] = 'Спрайт/Предмет',
                        fullToolName,
                        ["назв"] = toolName,
                        ["ссылка"] = tool
                    }
                    toolCell = ( sortable and 'data-sort-value="' .. toolName .. '" |' or '' ) .. image
                    table.insert( categories, spriteCat )
                end
                table.insert( cells, '|' .. toolCell )
            end
        end

        local choices = {}
        local function getChoice( choice, text )
            if not choices[choice] then
                choices[choice] = f:expandTemplate{ title = 'Таблица выбора', args = { choice, ''} }
            end
            return choices[choice] .. text
        end

        local function processTime( num )
            -- переданное число было умножено на 100
            if num <= 5 then        -- Минимальные временные затраты на разрушение блока равны 1 игровому такту (0,05 секунды)
                num = 0.05
            else                    -- Блоки должны быть разрушены кратно 1 игровому такту (0,05 секунды)
                num = math.ceil( num / 5 ) / 20
            end
            return num
        end

        if hardnessVal == '?' then
            fillCells( cells, '|?', numberMaterials + 1 )
        else
            if unbreakable then
                table.insert( cells, '| ' .. ( sortable and 'data-sort-value="999" ' or '' ) .. getChoice( 'no', '∞' ) )
                if showTool then
                    fillCells( cells, '|—', numberMaterials )
                end
            else
                local drop = 'да'
                local forceDrop = false
                if blockArgs["дроп"] == '0' then
                    drop = 'частично'
                elseif blockArgs["дроп"] == '1' then
                     forceDrop = 'да'
                 end
                 local requiredLevel = unbreakable and 999 or materialGrade[material]
                 local function insertMaterialCell( material )
                     local shouldDrop = drop
                    if materialGrade[material] < requiredLevel then
                        shouldDrop = 'нет'
                    end
                    -- предотвращение потери точности числа с плавающей запятой: умножить его на 100 и разделить в функции "processTime"
                    local breakTime = processTime( hardnessVal * (shouldDrop == 'нет' and 500 or 150) / materialSpeed[material] )
                    if breakTime == 0.05 then
                        shouldDrop = "запланировано"
                    end
                    table.insert( cells, '|' .. getChoice( forceDrop or shouldDrop, breakTime ) )
                end

                 if not showTool or tool == 'Любой' or tool == 'Нет' then
                     insertMaterialCell( 'Любой' )
                    if showTool then
                        fillCells( cells, '|—', numberMaterials )
                    end
                else
                    for _, material in ipairs{ 'Любой', 'Деревянный', 'Каменный', 'Железный', 'Алмазный', 'Незеритовый', 'Золотой' } do
                        insertMaterialCell( material )
                    end
                end
            end
        end

        if not simple and ( showShears or showSword ) then
            local tools = {}
            if showShears then
                table.insert( tools, 'Ножницы' )
            end
            if showSword then
                table.insert( tools, 'Меч' )
            end
            if hardnessVal == '?' then
                fillCells( cells, '|?', #tools )
            else
                local toolSpeed = {
                    ["Ножницы"] = 1,
                    ["Меч"] = 1.5
                }
                if blocks[1] == 'Шерсть' then
                    toolSpeed["Ножницы"] = 5
                elseif blocks[1] == 'Листва' then
                    toolSpeed["Ножницы"] = 15
                elseif blocks[1] == 'Паутина' then
                    toolSpeed["Меч"] = 15
                    toolSpeed["Ножницы"] = 15
                elseif blocks[1] == 'Бамбук' then
                    toolSpeed["Меч"] = 5000
                end

                for _, tool in ipairs( tools ) do
                    local toolDrop = blockArgs[mw.ustring.lower( tool )]
                    if not toolDrop then
                        table.insert( cells, '|—' )
                    else
                        local willDrop = 'да'
                        if toolDrop == '0' then
                            willDrop = 'частично'
                        end
                        -- предотвращение потери точности числа с плавающей запятой: умножить его на 100 и разделить в функции "processTime"
                        local breakTime = processTime( hardnessVal * 150 / toolSpeed[tool] )
                        if breakTime == 0.05 then
                            willDrop = "запланировано"
                        end
                        table.insert( cells, '|' .. getChoice( willDrop, breakTime ) )
                    end
                end
            end
        end

        if not horizontal then
            cells = table.concat( cells, '\n' )
        end
        table.insert( tableParts, cells )
    end

    if horizontal then
        local blocksArgs = {}
        for _, arg in ipairs{ 1, 'прим', 'спрайт', 'ссылка', 'предмет', 'дроп', 2, 3, 'ножницы', 'меч' } do
            if args[arg] then
                local col = 0
                for colVal in mw.text.gsplit( args[arg], '%s*;%s*' ) do
                    col = col + 1
                    if colVal ~= '' then
                        if not blocksArgs[col] then
                            blocksArgs[col] = {}
                        end

                        blocksArgs[col][arg] = colVal
                    end
                end
            end
        end
        for _, block in ipairs( blocksArgs ) do
            insertBlock( block )
        end

        local columns = #tableParts
        for row = 1, #tableParts[1] do
            local cells = {}
            for col = 1, columns do
                table.insert( cells, tableParts[col][row] )
            end
            table.insert( rows, table.concat( cells, '\n' ) )
        end

        -- Вставка заголовка времени разрушения после строки блока при "simple", или после строки инструмента или твердости, если "simple" не используется
        table.insert( rows, simple and 3 or showTool and 5 or 4, '! colspan="' .. columns + 1 .. '" |' .. getBreakingTimeHeader( f ) )
    else
        insertBlock( args )
        for _, row in ipairs( tableParts ) do
            table.insert( rows, row )
        end
    end
    table.insert( rows, '' )

    local note = ''
    if args["подвал"] or horizontal then
        note = f:preprocess( '<references group="FN"/>' )

        if args["подвал"] == '2' then
            table.insert( rows, header or getDplVar( 'header' ) )
        end
        table.insert( rows, '|}' )

        if not horizontal then
            f:callParserFunction( '#dplvar:set',
                'breaking header', '',
                'breaking hidetool', '',
                'breaking hideshears', '',
                'breaking hidesword', '',
                'breaking simple', '',
                'breaking sortable', ''
            )
        end
    elseif #dplVars > 0 then
         f:callParserFunction( '#dplvar:set', dplVars )
    end

    return table.concat( rows, '\n|-\n' ) .. note .. table.concat( categories )
end
return p
Advertisement