CCCPaste

Obmennik

--[[
The specified software is distributed under the CC0 license
No Rights Reserved
]] --

local ore_dict = {
    {
        "Железная руда",
        "Железный слиток",
        take = {name = "minecraft:iron_ore", damage = 0},
        give = {name = "minecraft:iron_ingot", damage = 0},
        rate = {take = 3, give = 7}
    },
    {
        "Кварцевая руда",
        "Кварц",
        take = {name = "minecraft:quartz_ore", damage = 0},
        give = {name = "minecraft:quartz", damage = 0},
        rate = {take = 1, give = 4}
    },
    {
        "Золотая руда",
        "Золотой слиток",
        take = {name = "minecraft:gold_ore", damage = 0},
        give = {name = "minecraft:gold_ingot", damage = 0},
        rate = {take = 3, give = 7}
    },
    {
        "Лазуритовая руда",
        "Лазурит",
        take = {name = "minecraft:lapis_ore", damage = 0},
        give = {name = "minecraft:dye", damage = 4},
        rate = {take = 1, give = 9}
    },
    {
        "Красная руда",
        "Красная пыль",
        take = {name = "minecraft:redstone_ore", damage = 0},
        give = {name = "minecraft:redstone", damage = 0},
        rate = {take = 1, give = 5}
    },
    {
        "Медная руда",
        "Медный слиток",
        take = {name = "IC2:blockOreCopper", damage = 0},
        give = {name = "IC2:itemIngot", damage = 0},
        rate = {take = 3, give = 7}
    },
    {
        "Оловянная руда",
        "Оловянный слиток",
        take = {name = "IC2:blockOreTin", damage = 0},
        give = {name = "IC2:itemIngot", damage = 1},
        rate = {take = 3, give = 7}
    },
    {
        "Оловянная руда",
        "Оловянный слиток",
        take = {name = "NetherOres:tile.netherores.ore.0", damage = 7},
        give = {name = "IC2:itemIngot", damage = 1},
        rate = {take = 3, give = 7}
    },
    {
        "Дракониевая руда",
        "Дракониевый слиток",
        take = {name = "DraconicEvolution:draconiumOre", damage = 0},
        give = {name = "DraconicEvolution:draconiumIngot", damage = 0},
        rate = {take = 1, give = 3}
    }
}

local unicode = require("unicode")
local computer = require("computer")
local com = require("component")
local event = require("event")
local me = com.isAvailable("me_interface") and com.me_interface or error("нет ме интерфейса")
local pim = com.isAvailable("pim") and com.pim or error("нет пима")

local gpu = com.gpu
local w, h = 80, 50
local defBG, defFG = gpu.getBackground(), gpu.getForeground()
gpu.setResolution(w, h)

local function center(height, text, color)
    gpu.setForeground(color)
    gpu.set(math.floor(w / 2 - unicode.len(text) / 2), height, text)
end

local function populateQty()
    local totalOre = 0
    for i, ore in pairs(ore_dict) do
    	local fingerprint = {id = ore.give.name, damage = ore.give.damage}
        local item = me.getItemDetail(fingerprint).basic()
        if item == nil then
            return 0
        else
            ore.sizeOfStack = item.max_size
            ore.qty = item.qty
            totalOre = totalOre + item.qty
        end
    end
    return totalOre
end

local function displayOres()
    local line = 2
    for i, ore in pairs(ore_dict) do
        local print_row = line + (i)

        gpu.setForeground(0x00ff00)
        gpu.set(5, print_row, ore[1])
        gpu.set(42, print_row, ore[2])

        gpu.setForeground(0xFF00FF)
        gpu.set(28, print_row, tostring(ore.rate.take))
        gpu.set(34, print_row, tostring(ore.rate.give))
        gpu.set(73, print_row, tostring(ore.qty))

        gpu.setForeground(0xFFFF00)
        gpu.set(30, print_row, "-->")
        gpu.set(63, print_row, "Доступно:")
        gpu.setForeground(0x202020)
        gpu.set(2, print_row + 1, string.rep("═", w - 2))
        line = line + 1
    end
end

local function updateOres()
    local totalOre = populateQty()
    gpu.fill(1, 1, w, h - 16, " ")
    if totalOre == 0 then
        gpu.fill(1, 1, w, h - 15, " ")
        center(h - 15, "Нет соединения с МЭ", 0xff0000)
    else
        displayOres()
    end
end

local function giveItemFromMe(item, dmg, amount)
    local fingerprint = {id = item, dmg = dmg}
    local err, res = pcall(me.exportItem, fingerprint, "UP", amount)
    if err == true then
    	return res.size
    end
end

local function giveIngot(toGive, ore)
    local totalGive = 0
    local givePreIteration = 0
    while totalGive < toGive do
        if toGive - totalGive > 64 then
            givePreIteration = ore.sizeOfStack
        else
            givePreIteration = toGive - totalGive
        end

        local gived = giveItemFromMe(ore.give.name, ore.give.damage, givePreIteration)

        totalGive = totalGive + gived
        if gived == 0 then
            gpu.fill(1, h - 15, w, 2, " ")
            center(h - 15, "Oсвободите место в инвентаре", 0xff0000)
            center(h - 14, "Ожидаю выдать " .. tostring(toGive - totalGive) .. " " .. ore[2], 0xFFFFFF)
            os.sleep(1)
        end
        gpu.fill(1, h - 15, 2, h, " ")
    end
end

local function exchangeOre(slot, ore)
    local curSlot = pim.getStackInSlot(slot)
    if curSlot == nil then
        center(h - 14, "Вы сошли с PIM, обмен прерван. (Не удалось прочесть слот)", 0xff0000)
        os.sleep(0.5)
        return
    end
    local userOreQty = curSlot.qty
    local takeQty = userOreQty - (userOreQty % ore.rate.take)
    local giveQty = userOreQty * ore.rate.give
    if ore.qty < giveQty then
        gpu.fill(1, h - 14, w, 1, " ")
        center(h - 14, "Недостаточно слитков для обмена <" .. ore[1] .. ">", 0xff0000)
        os.sleep(0.5)
        return
    end
    -- Количетсво могло измениться..
    local takedOre = pim.pushItem("DOWN", slot, takeQty)

    if takedOre == nil then
        gpu.fill(1, h - 14, w, 1, " ")
        center(h - 14, "Вы сошли с PIM, обмен прерван. (Не удалось извлечь руду)", 0xff0000)
        os.sleep(0.5)
    elseif takedOre == 0 then
        gpu.fill(1, h - 14, w, 1, " ")
        center(h - 14, "В выбраном слоте руды нет.. А была.. Хмм...", 0x505050)
    else
        local giveQty = (takedOre // ore.rate.take) * ore.rate.give
        gpu.fill(1, h - 15, w, 2, " ")
        center(h - 14, "Меняю  " .. takedOre .. "  " .. ore[1] .. "  на  " .. giveQty .. "  " .. ore[2], 0xffffff)
        giveIngot(giveQty, ore)
    end
end

local function checkInventory()
    local size = pim.getInventorySize()
    local data = pim.getAllStacks(0)

    for slot = 1, size do
        if data[slot] then
            for i, ore in pairs(ore_dict) do
                if data[slot].id == ore.take.name and data[slot].dmg == ore.take.damage then
                    exchangeOre(slot, ore)
                end
            end
        end
    end

    updateOres()

    if pim.getInventoryName() ~= "pim" then
        gpu.fill(1, h - 15, w, 2, " ")
        center(h - 15, "Обмен окончен! Приходите ещё!", 0xffffff)

        checkInventory()
    else
        -- Может быть, мы не поймали событие когда юзер ушел
        event.push("player_off")
    end
end

function handleEvent(eventID, ...)
    local args = {...}
    if eventID == "interrupted" then
        gpu.setBackground(defBG)
        gpu.setForeground(defFG)
        gpu.fill(1, 1, w, h, " ")
        os.exit()
        return true
    elseif eventID == "player_on" then
        gpu.fill(1, h - 15, w, 1, " ")
        center(h - 15, "Приветствую, " .. args[1] .. "! Начинаю обмен", 0xffffff)
        updateOres()
        checkInventory()
    elseif eventID == "player_off" then
        gpu.fill(1, h - 15, w, 1, " ")
        center(h - 15, "Для обмена встаньте на PIM и не сходите до окончания обмена", 0xffffff)
        updateOres()
    end
end

function drawStat()
    gpu.setForeground(0x444444)
    gpu.set(
        2,
        h - 1,
        string.format(
            "RAM: %.1fkB / %.1fkB",
            (computer.totalMemory() - computer.freeMemory()) / 1024,
            computer.totalMemory() / 1024
        )
    )
end

local oreTimeFn = function()
    updateOres()
    -- Каджый 10 такт обновляем экран
    for i = 1, 10 do
        coroutine.yield()
    end
end
local oreTimer = coroutine.create(oreTimeFn)

function draw_img(img, x, y, fore, back)
    fore = fore or 0xffffff
    back = back or 0x0
    oldFG = gpu.getForeground()
    gpu.setForeground(fore)
    local i = 0
    for line in img:gmatch("([^\n]*)\n?") do
        gpu.set(x, y + i, line)
        i = i + 1
    end
    gpu.setForeground(oldFG)
end
local img =
    [[
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡐⢆⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠠⡐⣄⢢⡐⢄⢢⡐⣄⠂⡄⠀⠀⢄⢢⢰⣀⢦⡐⣄⢢⡐⠄⣂⠆⠀⠀⢀⡐⢦⠹⠌⠀⢀⡰⢠⠀⠐⣠⠀⠀⠀⠀⠀⠀⠀⠀⠄⡐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢡⠂⡄⠀⠀⠀⠀⠌⡤⠃⠀⢳⡌⠃⠘⠈⠂⠑⠈⠑⠀⠀⡜⡢⠍⠂⠑⠈⠑⠈⠃⠀⠐⣌⠎⢀⡐⠦⣜⠂⠁⠀⠀⠀⡜⡡⠂⠘⠤⡁⠀⠀⠀⠀⠀⠀⠀⢂⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢢⠑⡌⢢⠀⠤⣉⡜⣰⠁⠀⡣⢝⠀⠀⠀⠀⠀⠀⠀⠀⢀⠳⣹⢌⡱⢢⡱⢌⢲⢰⡀⠀⢎⠺⣤⣙⠳⣀⠀⠀⠀⠀⠠⣙⠦⠁⢨⣑⠂⠀⠀⠀⠀⠀⠀⠀⢌⠳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢢⡑⠈⠒⡭⠒⠌⠸⣡⠃⠀⣙⠮⡄⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠈⠁⠁⠉⣈⠞⡢⠄⠈⢎⡳⠂⠉⠳⢆⡆⣀⠀⠀⠐⡌⠦⠁⠠⣃⠎⠀⠀⠀⠀⠀⠀⠀⠌⢒⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠒⡄⠁⠀⠀⠁⠀⠰⣡⠂⠀⠈⠸⣑⢋⢆⢳⡘⣔⠣⢆⢠⠱⣊⡕⣎⢖⡱⢎⠞⠁⠀⠈⣎⠱⠀⠀⠀⠈⠲⣡⠢⠄⠀⡜⡡⠂⠐⡥⢊⡴⢡⠎⡤⢁⠆⠀⠘⡀⠎⡐⢂⠰⠀⠆⡀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⢌⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ]]

function copyleft()
    local text = {
        {"Авторы: ", 0x444444, w - 35},
        {"Rijen, Furryonelove", 0x64fff2, w - 28}
    }
    local startPos = w - 32
    for i, str in pairs(text) do
        gpu.setForeground(str[2])
        gpu.set(str[3], h - 1, str[1])
    end

    gpu.setBackground(defBG)
    gpu.setForeground(defFG)
end

gpu.fill(1, 1, w, h, " ")
center(h - 15, "Для обмена встаньте на PIM и не сходите до окончания обмена", 0xffffff)
draw_img(img, 1, h - 13, 0x00a400)
copyleft()

while true do
    drawStat()

    handleEvent(event.pull(1))

    if coroutine.status(oreTimer) == "dead" then
        oreTimer = coroutine.create(oreTimeFn)
    else
        coroutine.resume(oreTimer)
    end
end