local player = require("player") local creator = require("creator") local world = require("world") -- Colors (RGBA, 0-255 range) local startSideColor = { 25, 252, 25, 75 } -- green, half alpha local endSideColor = { 255, 25, 25, 75 } -- red, half alpha local startLineColor = { 25, 252, 25, 200 } -- green local endLineColor = { 255, 25, 25, 200 } -- red registerWorldRenderer(function(ctx) local brokeInfo = world.getBreakingBlocksInfo() for _, breakResult in ipairs(brokeInfo) do local progress = breakResult.progress local pos = breakResult.blockpos local normalized = progress / 9 local shrinkFactor = 1 - normalized -- Получаем реальные аутлайны блока из мира local block = world.getBlock(pos.x, pos.y, pos.z) if not block then return end local outlineBoxes = world.getOutlineBoxes(pos.x, pos.y, pos.z, block) if not outlineBoxes or #outlineBoxes == 0 then return end -- Интерполируем цвета local sideR = startSideColor[1] + (endSideColor[1] - startSideColor[1]) * normalized local sideG = startSideColor[2] + (endSideColor[2] - startSideColor[2]) * normalized local sideB = startSideColor[3] + (endSideColor[3] - startSideColor[3]) * normalized local sideA = startSideColor[4] + (endSideColor[4] - startSideColor[4]) * normalized local lineR = startLineColor[1] + (endLineColor[1] - startLineColor[1]) * normalized local lineG = startLineColor[2] + (endLineColor[2] - startLineColor[2]) * normalized local lineB = startLineColor[3] + (endLineColor[3] - startLineColor[3]) * normalized local lineA = startLineColor[4] + (endLineColor[4] - startLineColor[4]) * normalized -- Рассчитываем центр для текста (усредняем по всем боксам) local totalMinX, totalMinY, totalMinZ = math.huge, math.huge, math.huge local totalMaxX, totalMaxY, totalMaxZ = -math.huge, -math.huge, -math.huge for i, box in ipairs(outlineBoxes) do local x1 = box.minX + pos.x local y1 = box.minY + pos.y local z1 = box.minZ + pos.z local x2 = box.maxX + pos.x local y2 = box.maxY + pos.y local z2 = box.maxZ + pos.z -- Сжимаем бокс на основе прогресса local xLen = x2 - x1 local yLen = y2 - y1 local zLen = z2 - z1 local shrunkXLen = xLen * shrinkFactor local shrunkYLen = yLen * shrinkFactor local shrunkZLen = zLen * shrinkFactor local xInset = (xLen - shrunkXLen) / 2 local yInset = (yLen - shrunkYLen) / 2 local zInset = (zLen - shrunkZLen) / 2 local sx1 = x1 + xInset local sy1 = y1 + yInset local sz1 = z1 + zInset local sx2 = x2 - xInset local sy2 = y2 - yInset local sz2 = z2 - zInset -- Создаём бокс через creator local shrunkBox = creator.createBox(sx1, sy1, sz1, sx2, sy2, sz2) -- Рендерим заполненный бокс (стороны) ctx.renderFilled(shrunkBox, sideR, sideG, sideB, sideA, true) -- Рендерим аутлайн (линии) ctx.renderOutline(shrunkBox, lineR, lineG, lineB, lineA, 4, true) -- Обновляем общие границы для расчёта центра totalMinX = math.min(totalMinX, sx1) totalMinY = math.min(totalMinY, sy1) totalMinZ = math.min(totalMinZ, sz1) totalMaxX = math.max(totalMaxX, sx2) totalMaxY = math.max(totalMaxY, sy2) totalMaxZ = math.max(totalMaxZ, sz2) end -- Рендерим текст с процентом в центре объединённой области local progressText = string.format("%.0f%%", normalized * 100) local centerX = (totalMinX + totalMaxX) / 2 local centerY = (totalMinY + totalMaxY) / 2 local centerZ = (totalMinZ + totalMaxZ) / 2 ctx.renderText(centerX, centerY, centerZ, progressText, 0.65, 255, 255, 255, true) end end)