Skip to content

Instantly share code, notes, and snippets.

@Fingercomp
Last active January 9, 2016 07:31
Show Gist options
  • Save Fingercomp/64d811a08af2e7848c9d to your computer and use it in GitHub Desktop.
Save Fingercomp/64d811a08af2e7848c9d to your computer and use it in GitHub Desktop.

Revisions

  1. Fingercomp revised this gist Jan 9, 2016. 1 changed file with 66 additions and 50 deletions.
    116 changes: 66 additions & 50 deletions pc-craft.lua
    Original file line number Diff line number Diff line change
    @@ -104,17 +104,27 @@ local function updateList(onlyCrafted, prbar)
    if prbar and not DEBUG then gpu.fill(1, 1, w, h, " ") gpu.set(1, math.floor((h - 1) / 2), "Сбор данных с робота. Пожалуйста, подождите...") end
    local totalopers = CHESTX * CHESTY + 1
    local doneopers = 0
    if prbar then drawPrbar(math.ceil(h / 2), doneopers, totalopers) end
    local lastTime = 4
    if prbar then
    drawPrbar(math.ceil(h / 2), doneopers, totalopers)
    gpu.set(1, math.ceil(h / 2) + 1, "Оставшееся время: " .. CHESTX * CHESTY * 4 .. " секунд")
    end
    _G.stacks = {}
    for i = 1, CHESTX, 1 do
    _G.stacks[i] = {}
    for j = 1, CHESTY, 1 do
    local start = comp.uptime()
    _G.stacks[i][j] = unsrl(get("li")[6])
    if j ~= CHESTY then
    sendW("z", 1)
    end
    local timeTook = math.floor((comp.uptime() - start) * 100) / 100
    doneopers = doneopers + 1
    if prbar then drawPrbar(math.ceil(h / 2), doneopers, totalopers) end
    if prbar then
    drawPrbar(math.ceil(h / 2), doneopers, totalopers)
    gpu.fill(1, math.ceil(h / 2) + 1, w, 1, " ")
    gpu.set(1, math.ceil(h / 2) + 1, "Оставшееся время: " .. (totalopers - doneopers) * (math.ceil(timeTook) / 2) .. " секунд")
    end
    end
    if i ~= CHESTX then
    sendW("x", 1)
    @@ -124,7 +134,11 @@ local function updateList(onlyCrafted, prbar)
    end
    sendW("x", -(CHESTX - 1))
    doneopers = doneopers + 1
    if prbar then drawPrbar(math.ceil(h/ 2), doneopers, totalopers) end
    if prbar then
    drawPrbar(math.ceil(h / 2), doneopers, totalopers)
    gpu.fill(1, math.ceil(h / 2) + 1, w, 1, " ")
    gpu.set(1, math.ceil(h / 2) + 1, "Оставшееся время: 0 секунд")
    end
    end
    _G.stacks[0] = {}
    _G.stacks[0][0] = {}
    @@ -142,7 +156,7 @@ end


    local function quit()
    return
    sendW("t", 0)
    end

    local checkAvail -- Forward declaration
    @@ -177,8 +191,8 @@ local function pushItem(item, slot, qty)
    success = false
    run = 1
    while not success do
    if not places[run] then
    io.stderr:write("Ошибка в функции экспорта. Сброс.\n")
    if not places or not places[run] then
    io.stderr:write("Ошибка в функции экспорта. Сброс.\nПерезапустите программу с аргументом \"update\"\n")
    moveTo(1, 1)
    sendW("t", 0)
    sendW("clear")
    @@ -261,7 +275,7 @@ end

    local tree = {}

    local function smartInsert(item, order, qty, noCraft, combine)
    local function smartInsert(item, order, qty, noCraft, combine, check)
    if DEBUG then print("SI", item, order, qty, noCraft, combine) end
    if qty == 0 then qty = 1 end -- O_O
    local new = true
    @@ -275,6 +289,17 @@ local function smartInsert(item, order, qty, noCraft, combine)
    end
    end
    end
    if not combine and check then
    for i = 1, #tree, 1 do
    -- Ninjafix the ninjafix
    if tree[i].item.fingerprint.id == item.fingerprint.id and
    tree[i].item.fingerprint.dmg == item.fingerprint.dmg and
    tree[i].qty == qty and
    tree[i].order == order then
    new = false
    end
    end
    end
    if new then
    if noCraft then
    table.insert(tree, {["item"] = item, ["order"] = order, ["qty"] = qty, ["noCraft"] = true})
    @@ -284,7 +309,7 @@ local function smartInsert(item, order, qty, noCraft, combine)
    end
    end

    local function buildTree(itemName, order, qty, itemStack, toCraft, combine)
    local function buildTree(itemName, order, qty, itemStack, toCraft, combine, check)
    if DEBUG then print(itemName, order, qty, itemStack, toCraft, combine) end
    local item = {}
    if itemName ~= nil then
    @@ -298,24 +323,15 @@ local function buildTree(itemName, order, qty, itemStack, toCraft, combine)
    end
    end
    if toCraft == nil then toCraft = false end
    if combine == nil then combine = false end
    smartInsert(item, order, qty, toCraft, combine)
    if combine == nil then combine = true end
    smartInsert(item, order, qty, toCraft, combine, check)
    if type(item.recipe) == "table" then
    for i = 1, 9, 1 do
    if item.recipe[i] ~= "" then
    if not checkAvail(item.recipe[i], _, false) then
    buildTree(item.recipe[i], order + 1, math.ceil(qty / item.qty), nil, false, true)
    buildTree(item.recipe[i], order + 1, math.ceil(qty / item.qty), nil, false, combine, check)
    else
    local recipeItem = getItem(item.recipe[i])
    local addToTree = false
    for _, j in pairs(tree) do
    if not (j.item.fingerprint.id == recipeItem.id and j.item.fingerprint.dmg == recipeItem.dmg) then
    addToTree = true
    end
    end
    if addToTree then
    smartInsert(getItem(item.recipe[i]), order + 1, math.ceil(qty / item.qty), true, true)
    end
    smartInsert(getItem(item.recipe[i]), order + 1, math.ceil(qty / item.qty), true, combine, check)
    end
    end
    end
    @@ -342,7 +358,7 @@ local function checkTree()
    if DEBUG then print("CS", info.size) end
    if stack.qty > size then
    if stack.item.recipe then
    buildTree(nil, stack.order + 1, stack.qty - info.size, stack.item, false, false)
    buildTree(nil, stack.order + 1, stack.qty - info.size, stack.item, false, false, true)
    else
    io.stderr:write("[ERR] Недостаточно ресурсов: " .. stack.item.fingerprint.id .. "@" .. stack.item.fingerprint.dmg .. " (" .. size .. "/" .. stack.qty .. ")!")
    quit()
    @@ -352,7 +368,7 @@ local function checkTree()
    else
    if stack.item.recipe then
    if DEBUG then print("M", stack.qty) end
    buildTree(nil, stack.order + 1, stack.qty, stack.item, false, false)
    buildTree(nil, stack.order + 1, stack.qty, stack.item, false, false, true)
    else
    io.stderr:write("[ERR] Отсутствие ресурсов: " .. stack.item.fingerprint.id .. "@" .. stack.item.fingerprint.dmg .. " (" .. stack.qty .. ")!")
    quit()
    @@ -557,7 +573,7 @@ for i =1, #tree, 1 do
    else
    noCraft = ""
    end
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order ..")")
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
    end
    gpu.set(1, h, "Нажмите [Enter] для проверки дерева и старта крафта...")
    local keyData = {event.pull("key_down")}
    @@ -567,36 +583,36 @@ if keyData[1] == nil or keyData[3] ~= 13 then
    quit()
    os.exit()
    end
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("ПЛАН КРАФТА (ПЕРЕПРОВЕРКА)", 1)
    print("[INFO] Проверка плана...")
    while true do
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("ПЛАН КРАФТА (ПЕРЕПРОВЕРКА)", 1)
    print("[INFO] Проверка плана...")
    local lastLen = #tree
    checkTree()
    for i = 1, #tree, 1 do
    if tree[i].noCraft then
    noCraft = "[X]"
    else
    noCraft = ""
    end
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
    end
    print("\n")
    gpu.set(1, h - 1, "Нажмите [Enter] для начала крафта")
    gpu.set(1, h, "Нажмите [Space] для повторной проверки")
    keyData = {event.pull("key_down")}
    if keyData[1] == nil or keyData[3] ~= 13 and keyData[3] ~= 32 then
    term.clear()
    term.setCursor(1, 1)
    quit()
    os.exit()
    elseif keyData[3] == 32 then
    checkTree()
    elseif keyData[3] == 13 then
    local treeLen = #tree
    if treeLen == lastLen then
    break
    end
    end
    for i = 1, #tree, 1 do
    if tree[i].noCraft then
    noCraft = "[X]"
    else
    noCraft = ""
    end
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
    end
    print("")
    gpu.set(1, h, "Нажмите [Enter] для начала крафта")
    keyData = {event.pull("key_down")}
    if keyData[1] == nil or keyData[3] ~= 13 then
    term.clear()
    term.setCursor(1, 1)
    quit()
    os.exit()
    end
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    @@ -614,4 +630,4 @@ print("[INFO] [Stats] Длина дерева: " .. stats.treeLen .. "\n")
    gpu.set(1, h - 1, string.rep("-", w))
    centerY("КРАФТ ЗАВЕРШЁН", h - 1)
    term.setCursor(1, h)
    sendW("t", 0)
    quit()
  2. Fingercomp revised this gist Jan 4, 2016. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions pc-recipes.lua
    Original file line number Diff line number Diff line change
    @@ -313,7 +313,7 @@ local function scanRecipe()
    print("")
    local id = recipe[10].name
    local meta = recipe[10].damage
    local max = recipes[10].maxSize
    local max = recipe[10].maxSize
    local qty, rcp = 1, {}
    local makeRcp = false
    for i =1, 9, 1 do
    @@ -335,6 +335,7 @@ local function scanRecipe()
    for i = 1, 9, 1 do
    if recipe[i] ~= "" and recipe[i] ~= nil then
    for rcpName, stack in pairs(recipes) do
    -- print(rcpName, stack.fingerprint.id, stack.fingerprint.dmg, recipe[i].name, recipe[i].damage)
    if recipe[i].name == stack.fingerprint.id and recipe[i].damage == stack.fingerprint.dmg then
    rcp[i] = rcpName
    end
    @@ -417,7 +418,7 @@ while true do
    print(" [7] Сканирование рецепта")
    io.write("Выберите действие: ")
    mode = term.read()
    until tonumber(mode) ~=nil and tonumber(mode) < 8 and tonumber(mode) > -1
    until tonumber(mode) ~= nil and tonumber(mode) < 8 and tonumber(mode) > -1

    mode = tonumber(mode)

  3. Fingercomp revised this gist Jan 4, 2016. 1 changed file with 13 additions and 4 deletions.
    17 changes: 13 additions & 4 deletions pc-craft.lua
    Original file line number Diff line number Diff line change
    @@ -88,7 +88,7 @@ end
    local function drawPrbar(line, cur, max)
    if not DEBUG then
    local width = w - 7
    localoneperc = width / 100
    local oneperc = width / 100
    local curwidth = math.floor(cur / max * oneperc * 100)
    gpu.set(1, line, "" .. string.rep(" ", width) .. "" .. math.floor(cur / max * 100) .. "%")
    gpu.set(2, line, string.rep("", curwidth))
    @@ -306,7 +306,16 @@ local function buildTree(itemName, order, qty, itemStack, toCraft, combine)
    if not checkAvail(item.recipe[i], _, false) then
    buildTree(item.recipe[i], order + 1, math.ceil(qty / item.qty), nil, false, true)
    else
    smartInsert(getItem(item.recipe[i]), order + 1, math.ceil(qty / item.qty), true, true)
    local recipeItem = getItem(item.recipe[i])
    local addToTree = false
    for _, j in pairs(tree) do
    if not (j.item.fingerprint.id == recipeItem.id and j.item.fingerprint.dmg == recipeItem.dmg) then
    addToTree = true
    end
    end
    if addToTree then
    smartInsert(getItem(item.recipe[i]), order + 1, math.ceil(qty / item.qty), true, true)
    end
    end
    end
    end
    @@ -329,7 +338,7 @@ local function checkTree()
    local avail, info, _, size = checkAvail(nil, stack.item, false)
    if DEBUG then print("AQ", avail, stack.qty, type(stack.qty)) end
    if stack.noCraft then
    if avail then
    if avail then
    if DEBUG then print("CS", info.size) end
    if stack.qty > size then
    if stack.item.recipe then
    @@ -548,7 +557,7 @@ for i =1, #tree, 1 do
    else
    noCraft = ""
    end
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order ..")")
    end
    gpu.set(1, h, "Нажмите [Enter] для проверки дерева и старта крафта...")
    local keyData = {event.pull("key_down")}
  4. Fingercomp revised this gist Jan 4, 2016. 2 changed files with 3 additions and 2 deletions.
    3 changes: 2 additions & 1 deletion pc-recipes.lua
    Original file line number Diff line number Diff line change
    @@ -370,7 +370,8 @@ local function scanRecipe()
    if apply == "y" or apply == "Y" or apply == "yes" or apply == "Yes" or apply == "YES" then
    if rcp[1] then
    recipes[name] = {
    fingerprint = {id = id,
    fingerprint = {
    id = id,
    dmg = meta,
    max = max
    },
    2 changes: 1 addition & 1 deletion robot-autorun.lua
    Original file line number Diff line number Diff line change
    @@ -188,7 +188,7 @@ local actions = {

    while true do
    local data = {event.pull("modem_message")}
    ifdata[6] then
    if data[6] then
    local msg = {}
    local args = {}
    for i = 6, #data, 1 do
  5. Fingercomp revised this gist Jan 4, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion pc-craft.lua
    Original file line number Diff line number Diff line change
    @@ -551,7 +551,7 @@ for i =1, #tree, 1 do
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
    end
    gpu.set(1, h, "Нажмите [Enter] для проверки дерева и старта крафта...")
    localkeyData = {event.pull("key_down")}
    local keyData = {event.pull("key_down")}
    if keyData[1] == nil or keyData[3] ~= 13 then
    term.clear()
    term.setCursor(1, 1)
  6. Fingercomp revised this gist Jan 4, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion pc-craft.lua
    Original file line number Diff line number Diff line change
    @@ -360,7 +360,7 @@ local function craft()
    stats.timeStart = comp.uptime()
    stats.timeStop = 0
    stats.treeLen = #tree
    localorderTree = {}
    local orderTree = {}
    for i = 1, #tree, 1 do
    local order = tree[i].order + 1
    if not orderTree[order] then
  7. Fingercomp revised this gist Jan 4, 2016. 3 changed files with 17 additions and 11 deletions.
    19 changes: 12 additions & 7 deletions pc-craft.lua
    Original file line number Diff line number Diff line change
    @@ -248,7 +248,8 @@ checkAvail = function(itemName, item, updList)
    if DEBUG then print("CA", true, stackinfo, i, j, slot) end
    end
    end
    endend
    end
    end
    if data == false then
    if DEBUG then print("CA", false) end
    return false
    @@ -299,7 +300,7 @@ local function buildTree(itemName, order, qty, itemStack, toCraft, combine)
    if toCraft == nil then toCraft = false end
    if combine == nil then combine = false end
    smartInsert(item, order, qty, toCraft, combine)
    iftype(item.recipe) == "table" then
    if type(item.recipe) == "table" then
    for i = 1, 9, 1 do
    if item.recipe[i] ~= "" then
    if not checkAvail(item.recipe[i], _, false) then
    @@ -328,7 +329,8 @@ local function checkTree()
    local avail, info, _, size = checkAvail(nil, stack.item, false)
    if DEBUG then print("AQ", avail, stack.qty, type(stack.qty)) end
    if stack.noCraft then
    if avail then if DEBUG then print("CS", info.size) end
    if avail then
    if DEBUG then print("CS", info.size) end
    if stack.qty > size then
    if stack.item.recipe then
    buildTree(nil, stack.order + 1, stack.qty - info.size, stack.item, false, false)
    @@ -339,7 +341,8 @@ local function checkTree()
    end
    end
    else
    if stack.item.recipe then if DEBUG then print("M", stack.qty) end
    if stack.item.recipe then
    if DEBUG then print("M", stack.qty) end
    buildTree(nil, stack.order + 1, stack.qty, stack.item, false, false)
    else
    io.stderr:write("[ERR] Отсутствие ресурсов: " .. stack.item.fingerprint.id .. "@" .. stack.item.fingerprint.dmg .. " (" .. stack.qty .. ")!")
    @@ -431,7 +434,8 @@ end
    local names = {}

    for name, _ in pairs(recipes) do
    table.insert(names, name)end
    table.insert(names, name)
    end

    local pages = {}
    local onPage = listH * 2
    @@ -459,7 +463,8 @@ local lines = {}
    local function list(page)
    term.clear()
    for i = 1, #pages[page], 1 do
    local item = pages[page][i] local nonCraftable = (recipes[item[2] ].recipe and "[*] " or "")
    local item = pages[page][i]
    local nonCraftable = (recipes[item[2] ].recipe and "[*] " or "")
    if i > listH then
    gpu.set(w / 2, i - listH, "[" .. item[1] .. "] " .. nonCraftable .. item[2])
    else
    @@ -502,7 +507,7 @@ for i = 1, #pages[page], 1 do
    id = i
    end
    end
    ifid > listH then
    if id > listH then
    lineH = id - listH
    offset = w / 2
    else
    6 changes: 3 additions & 3 deletions pc-recipes.lua
    Original file line number Diff line number Diff line change
    @@ -155,7 +155,8 @@ local function addRecipe(edit)
    print("Слот #" .. i)
    print("(оставьте пустым для пропуска):")
    io.write(": ")
    item = term.read(history, nil, hint) table.insert(recipe, unicode.sub(item, 1, -2))
    item = term.read(history, nil, hint)
    table.insert(recipe, unicode.sub(item, 1, -2))
    print("Записано: " .. recipe[i] .. "\n")
    end
    end
    @@ -285,7 +286,7 @@ local function showRecipe()
    end
    end

    localfunction scanRecipe()
    local function scanRecipe()
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    @@ -334,7 +335,6 @@ localfunction scanRecipe()
    for i = 1, 9, 1 do
    if recipe[i] ~= "" and recipe[i] ~= nil then
    for rcpName, stack in pairs(recipes) do
    -- print(rcpName, stack.fingerprint.id, stack.fingerprint.dmg, recipe[i].name, recipe[i].damage)
    if recipe[i].name == stack.fingerprint.id and recipe[i].damage == stack.fingerprint.dmg then
    rcp[i] = rcpName
    end
    3 changes: 2 additions & 1 deletion robot-autorun.lua
    Original file line number Diff line number Diff line change
    @@ -79,7 +79,8 @@ local function mvx(step, trn)
    turn(0)
    end
    if step > 0 then
    for i = 1, step, 1 do sfFw()
    for i = 1, step, 1 do
    sfFw()
    end
    elseif step < 0 then
    for i = 1, -step, 1 do
  8. Fingercomp revised this gist Jan 4, 2016. 5 changed files with 408 additions and 143 deletions.
    265 changes: 175 additions & 90 deletions pc-craft.lua
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@ local FILE = "/usr/share/db"
    local PORT = 666
    local TECH_SLOTS = 3
    local X, Y, Z = 0, 0, 0
    local CHESTX, CHESTY = 1, 2
    local CHESTX, CHESTY = 4, 3
    local DEBUG = false
    ---===---
    local com = require("component")
    @@ -19,10 +19,47 @@ local unsrl = require("serialization").unserialize

    local w, h = gpu.getResolution()
    local curx, cury = 1, 1
    local args = {...}
    modem.open(PORT)
    local stacks = {}

    if args[1] == "update" or not _G.stacks then
    _G.stacks = {}
    end


    local function split(items, size, max, inMax)
    local run = 1
    local runs = {}
    local ne = true
    while ne do
    if math.ceil(items / size) * size <= max and math.ceil(items / size) <= inMax then
    table.insert(runs, math.ceil(items / size))
    ne = false
    else
    a = 0
    for i = max, 1, -1 do
    if math.ceil(i / size) * size <= max and math.ceil(i / size) <= inMax then
    a = math.ceil(i / size)
    break
    end
    end
    table.insert(runs, a)
    items = items - a * size
    end
    run = run + 1
    if run % 10 == 0 then
    os.sleep(0.05)
    end
    end
    sum = 0
    for i = 1, #runs, 1 do
    sum = sum + runs[i] * size
    end
    return runs, sum
    end

    local function send(...)
    if DEBUG then print(" →: ", ...) end
    modem.broadcast(PORT, ...)
    end

    @@ -31,63 +68,77 @@ local function sendW(...)
    local data
    repeat
    data={event.pull(5, "modem_message")}
    until data[1] and data[6] == "done"
    until data[1] and data[6] == "done" and data[5] > 0.5
    end

    local function get(...)
    send(...)
    local data
    repeat
    data = {event.pull(5, "modem_message")}
    until data[1]
    until data[1] and data[6] ~= "done"
    local done
    repeat
    done = {event.pull(5, "modem_message")}
    until done[1] and done[6] == "done"
    until done[1] and done[6] == "done" and data[5] > 0.5
    if DEBUG then print("`get`", table.unpack(data)) end
    return data
    end

    local function drawPrbar(line, cur, max)
    local width = w - 7
    local oneperc = width / 100
    local curwidth = math.floor(cur / max * oneperc * 100)
    gpu.set(1, line, "|" .. string.rep(" ", width) .. "| " .. math.floor(cur / max * 100) .. "%")
    gpu.set(2, line, string.rep("", curwidth))
    if not DEBUG then
    local width = w - 7
    localoneperc = width / 100
    local curwidth = math.floor(cur / max * oneperc * 100)
    gpu.set(1, line, "" .. string.rep(" ", width) .. "" .. math.floor(cur / max * 100) .. "%")
    gpu.set(2, line, string.rep("", curwidth))
    else
    print(cur .. "/" .. max .. " (" .. math.floor(cur / max * 100) .. "%)")
    end
    end

    local function updateList(onlyCrafted, prbar)
    sendW("t", 3)
    if not onlyCrafted then
    if prbar then gpu.fill(1, 1, w, h, " ") gpu.set(1, math.floor((h - 1) / 2), "Сбор данных с робота. Пожалуйста, подождите...") end
    sendW("clear")
    if prbar and not DEBUG then gpu.fill(1, 1, w, h, " ") gpu.set(1, math.floor((h - 1) / 2), "Сбор данных с робота. Пожалуйста, подождите...") end
    local totalopers = CHESTX * CHESTY + 1
    local doneopers = 0
    if prbar then drawPrbar(math.ceil(h / 2), doneopers, totalopers) end
    stacks = {}
    sendW("t", 3)
    _G.stacks = {}
    for i = 1, CHESTX, 1 do
    stacks[i] = {}
    _G.stacks[i] = {}
    for j = 1, CHESTY, 1 do
    stacks[i][j] = unsrl(get("li")[6])
    sendW("z", 1)
    _G.stacks[i][j] = unsrl(get("li")[6])
    if j ~= CHESTY then
    sendW("z", 1)
    end
    doneopers = doneopers + 1
    if prbar then drawPrbar(math.ceil(h / 2), doneopers, totalopers) end
    end
    sendW("x", 2)
    sendW("z", -CHESTY)
    if i ~= CHESTX then
    sendW("x", 1)
    end
    sendW("z", -CHESTY + 1)
    sendW("t", 3)
    end
    sendW("x", CHESTX * -2)
    sendW("x", -(CHESTX - 1))
    doneopers = doneopers + 1
    if prbar then drawPrbar(math.ceil(h/ 2), doneopers, totalopers) end
    end
    stacks[0] = {}
    stacks[0][0] = {}
    stacks[0][0] = unsrl(get("lc")[6])
    _G.stacks[0] = {}
    _G.stacks[0][0] = {}
    _G.stacks[0][0] = unsrl(get("lc")[6])
    end
    loadfile(FILE, _ENV, _ENV)()
    sendW("x", X)
    sendW("y", Y)
    sendW("z", Z)
    updateList(_, true)
    if args[1] == "update" or not _G.stacks[0] or not _G.stacks[0][0] then
    updateList(_, true)
    elseif args[1] ~= "noupd" then
    updateList(true)
    end


    local function quit()
    @@ -103,7 +154,7 @@ local function centerY(text, line)
    end

    local function moveTo(i, j)
    moveX = (i - curx) * 2
    moveX = (i - curx)
    moveZ = (j - cury)
    if DEBUG then print("MT", i, j, "|", curx, cury, "=>", moveX, moveZ) end
    if moveX ~= 0 then
    @@ -119,12 +170,21 @@ end

    local function pushItem(item, slot, qty)
    local itemPrint = item.fingerprint
    local srlPrint = srl(itemPrint)
    local rslot = slot + math.floor((slot - 1) / 3)
    sendW("sel", rslot)
    _, _, places = checkAvail(_, item)
    _, _, places = checkAvail(_, item, false)
    success = false
    run = 1
    while not success do
    if not places[run] then
    io.stderr:write("Ошибка в функции экспорта. Сброс.\n")
    moveTo(1, 1)
    sendW("t", 0)
    sendW("clear")
    os.exit(-1)
    end
    if DEBUG then print("Push:runs", #places[run]) end
    if DEBUG then print("Push", run, rslot, qty, table.unpack(places[run])) end
    mtx, mtz, dir = places[run][1], places[run][2], 0
    if mtx == 0 and mtz == 0 then
    @@ -134,8 +194,8 @@ local function pushItem(item, slot, qty)
    end
    moveTo(mtx, mtz)
    cslot = places[run][3]
    if DEBUG then print("Push:1", cslot, qty, dir) end
    data = get("take", cslot, qty, dir)
    if DEBUG then print("Push:1", cslot, qty, dir, srlPrint) end
    data = get("take", cslot, qty, dir, srlPrint)
    success = data[6]
    sucked = data[7] or 0
    if DEBUG then print("Push:got", success, sucked) end
    @@ -145,38 +205,50 @@ local function pushItem(item, slot, qty)
    end
    run = run + 1
    end
    local ci, cj, cslot = table.unpack(places[run - 1])
    _G.stacks[ci][cj][cslot].size = _G.stacks[ci][cj][cslot].size - qty
    if _G.stacks[ci][cj][cslot].size == 0 then
    _G.stacks[ci][cj][cslot] = nil
    end
    end

    local function getItem(itemName)
    if not recipes[itemName] then
    io.stderr:write("В БД не найден рецепт: " .. itemName .. "!\n")
    os.exit(-1)
    end
    return recipes[itemName]
    end

    checkAvail = function(itemName, item)
    if DEBUG then print(itemName, item) end
    checkAvail = function(itemName, item, updList)
    if updList == nil then updList = true end
    if DEBUG then print("CA:got", itemName, item) end
    local itemStack
    if item == nil then
    itemStack = getItem(itemName)
    else
    itemStack = item
    end
    local itemFP = itemStack.fingerprint
    if DEBUG then print("CS:item", itemFP.id .. "@" .. itemFP.dmg) end
    local data = false
    local places = {}
    size = 0
    updateList(true)
    for i = 0, #stacks, 1 do
    for j = (i == 0 and 0 or 1), #stacks[i], 1 do
    if updList then
    updateList(true)
    end
    for i = 0, #_G.stacks, 1 do
    for j = (i == 0 and 0 or 1), #_G.stacks[i], 1 do
    if DEBUG then print("CA:S", i, j) end
    for slot, stackinfo in pairs(stacks[i][j]) do
    for slot, stackinfo in pairs(_G.stacks[i][j]) do
    if stackinfo.fingerprint.id == itemFP.id and stackinfo.fingerprint.dmg == itemFP.dmg then
    data = {true, stackinfo}
    table.insert(places, {i, j, slot})
    size = size + stackinfo.size
    if DEBUG then print("CA", true, stackinfo, i, j, slot) end
    end
    end
    end
    end
    endend
    if data == false then
    if DEBUG then print("CA", false) end
    return false
    @@ -190,6 +262,7 @@ local tree = {}

    local function smartInsert(item, order, qty, noCraft, combine)
    if DEBUG then print("SI", item, order, qty, noCraft, combine) end
    if qty == 0 then qty = 1 end -- O_O
    local new = true
    if combine then
    for i = 1, #tree, 1 do
    @@ -218,27 +291,32 @@ local function buildTree(itemName, order, qty, itemStack, toCraft, combine)
    elseif itemStack ~= nil then
    item = itemStack
    end
    if type(item.recipe) == "table" then
    if order == 0 then
    if (math.ceil(qty / item.qty) * item.qty) ~= qty then
    qty = math.ceil(qty / item.qty) * item.qty
    end
    end
    if toCraft == nil then toCraft = false end
    if combine == nil then combine = false end
    smartInsert(item, order, qty, toCraft, combine)
    iftype(item.recipe) == "table" then
    for i = 1, 9, 1 do
    if item.recipe[i] ~= "" then
    if not checkAvail(item.recipe[i]) then
    if not checkAvail(item.recipe[i], _, false) then
    buildTree(item.recipe[i], order + 1, math.ceil(qty / item.qty), nil, false, true)
    else
    smartInsert(getItem(item.recipe[i]), order + 1, math.ceil(qty / item.qty), true, true)
    end
    end
    end
    else
    if not checkAvail(itemName) then
    if not checkAvail(itemName, _, false) then
    io.stderr:write("Отсутствует компонент крафта: " .. item.fingerprint.id .. "@" .. item.fingerprint.dmg .. "!")
    quit()
    os.exit()
    end
    end
    if toCraft == nil then toCraft = false end
    if combine == nil then combine = true end
    if DEBUG then print("TC", toCraft, combine) end
    smartInsert(item, order, qty, toCraft, combine)
    end

    local stack = {}
    @@ -247,11 +325,10 @@ local function checkTree()
    for i = 1, #tree, 1 do
    local stack = tree[i]
    if DEBUG then print("ID", stack.item.fingerprint.id, stack.item.fingerprint.dmg) end
    local avail, info, _, size = checkAvail(nil, stack.item)
    local avail, info, _, size = checkAvail(nil, stack.item, false)
    if DEBUG then print("AQ", avail, stack.qty, type(stack.qty)) end
    if stack.noCraft then
    if avail then
    if DEBUG then print("CS", info.size) end
    if avail then if DEBUG then print("CS", info.size) end
    if stack.qty > size then
    if stack.item.recipe then
    buildTree(nil, stack.order + 1, stack.qty - info.size, stack.item, false, false)
    @@ -262,8 +339,7 @@ local function checkTree()
    end
    end
    else
    if stack.item.recipe then
    if DEBUG then print("M", stack.qty) end
    if stack.item.recipe then if DEBUG then print("M", stack.qty) end
    buildTree(nil, stack.order + 1, stack.qty, stack.item, false, false)
    else
    io.stderr:write("[ERR] Отсутствие ресурсов: " .. stack.item.fingerprint.id .. "@" .. stack.item.fingerprint.dmg .. " (" .. stack.qty .. ")!")
    @@ -281,7 +357,7 @@ local function craft()
    stats.timeStart = comp.uptime()
    stats.timeStop = 0
    stats.treeLen = #tree
    local orderTree = {}
    localorderTree = {}
    for i = 1, #tree, 1 do
    local order = tree[i].order + 1
    if not orderTree[order] then
    @@ -291,36 +367,37 @@ local function craft()
    end
    stats.maxOrder = #orderTree
    for i = #orderTree, 1, -1 do
    print("[INFO] [Craft] Обработка очереди " .. i)
    print("[INFO] [Craft] * Обработка очереди " .. i)
    for j = 1, #orderTree[i], 1 do
    print("[INFO] [Craft] Обработка задачи " .. j)
    print("[INFO] [Craft] * Обработка задачи " .. j)
    if orderTree[i][j].item.recipe then
    if not orderTree[i][j].noCraft then
    print("[INFO] [Craft] ID предмета в задаче: " .. orderTree[i][j].item.fingerprint.id .. "@" .. orderTree[i][j].item.fingerprint.dmg)
    iters = orderTree[i][j].qty
    craftSize = orderTree[i][j].item.qty
    riters = iters
    if DEBUG then print("RIters", riters) end
    runs = {}
    while true do
    if riters < 65 then
    table.insert(runs, math.ceil(riters / craftSize))
    break
    else
    table.insert(runs, math.ceil(64 / craftSize))
    updateList(true)
    print("[INFO] [Craft] ID предмета в задаче: " .. orderTree[i][j].item.fingerprint.id .. "@" .. orderTree[i][j].item.fingerprint.dmg)
    local iters = orderTree[i][j].qty
    local craftSize = orderTree[i][j].item.qty
    local max = orderTree[i][j].item.fingerprint.max
    local inMax = 64
    for p = 1, 9, 1 do
    if orderTree[i][j].item.recipe[p] ~= "" then
    if inMax > getItem(orderTree[i][j].item.recipe[p]).fingerprint.max then
    inMax = getItem(orderTree[i][j].item.recipe[p]).fingerprint.max
    end
    end
    riters = riters - 64
    end
    local runs = split(iters, craftSize, max, inMax)
    if DEBUG then print("Runs", table.unpack(runs)) end
    for l = 1, #runs, 1 do
    print("[INFO] [Craft] Крафт #" .. l .. " (кол-во: " .. runs[l] .. ")")
    if runs[l] == 0 then runs[l] = 1 end
    print("[INFO] [Craft] * Крафт #" .. l .. " (кол-во: " .. runs[l] .. ")")
    for k = 1, 9, 1 do
    if orderTree[i][j].item.recipe[k] ~= "" then
    print("[INFO] [Craft] * Слот: " .. k .. "/" .. 9)
    pushItem(getItem(orderTree[i][j].item.recipe[k]), k, runs[l])
    end
    end
    moveTo(1, 1)
    sendW("craft")
    sendW("craft", orderTree[i][j].item.fingerprint.max)
    stats.crafted = stats.crafted + runs[l]
    end
    end
    @@ -354,8 +431,7 @@ end
    local names = {}

    for name, _ in pairs(recipes) do
    table.insert(names, name)
    end
    table.insert(names, name)end

    local pages = {}
    local onPage = listH * 2
    @@ -383,8 +459,7 @@ local lines = {}
    local function list(page)
    term.clear()
    for i = 1, #pages[page], 1 do
    local item = pages[page][i]
    local nonCraftable = (recipes[item[2] ].recipe and "[*] " or "")
    local item = pages[page][i] local nonCraftable = (recipes[item[2] ].recipe and "[*] " or "")
    if i > listH then
    gpu.set(w / 2, i - listH, "[" .. item[1] .. "] " .. nonCraftable .. item[2])
    else
    @@ -427,7 +502,7 @@ for i = 1, #pages[page], 1 do
    id = i
    end
    end
    if id > listH then
    ifid > listH then
    lineH = id - listH
    offset = w / 2
    else
    @@ -471,40 +546,50 @@ for i =1, #tree, 1 do
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
    end
    gpu.set(1, h, "Нажмите [Enter] для проверки дерева и старта крафта...")
    local keyData = {event.pull("key_down")}
    localkeyData = {event.pull("key_down")}
    if keyData[1] == nil or keyData[3] ~= 13 then
    term.clear()
    term.setCursor(1, 1)
    quit()
    os.exit()
    end
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("ПЛАН КРАФТА (ПЕРЕПРОВЕРКА)", 1)
    print("[INFO] Проверка плана...")
    checkTree()
    for i = 1, #tree, 1 do
    if tree[i].noCraft then
    noCraft = "[X]"
    else
    noCraft = ""
    end
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
    end
    gpu.set(1, h, "Нажмите [Enter] для продолжения...")
    keyData = {event.pull("key_down")}
    if keyData[1] == nil or keyData[3] ~= 13 then
    while true do
    term.clear()
    term.setCursor(1, 1)
    quit()
    os.exit()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("ПЛАН КРАФТА (ПЕРЕПРОВЕРКА)", 1)
    print("[INFO] Проверка плана...")
    checkTree()
    for i = 1, #tree, 1 do
    if tree[i].noCraft then
    noCraft = "[X]"
    else
    noCraft = ""
    end
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
    end
    print("\n")
    gpu.set(1, h - 1, "Нажмите [Enter] для начала крафта")
    gpu.set(1, h, "Нажмите [Space] для повторной проверки")
    keyData = {event.pull("key_down")}
    if keyData[1] == nil or keyData[3] ~= 13 and keyData[3] ~= 32 then
    term.clear()
    term.setCursor(1, 1)
    quit()
    os.exit()
    elseif keyData[3] == 32 then
    checkTree()
    elseif keyData[3] == 13 then
    break
    end
    end
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("ЛОГ КРАФТА", 1)
    print("[ATTN] Пожалуйста, не изменяйте содержимое сундуков до завершения процесса крафта!")
    print("[INFO] [Main] Очистка инвентаря робота")
    sendW("clear")
    local stats = craft()
    print("")
    print("[INFO] [Stats] Статистика:")
    139 changes: 139 additions & 0 deletions pc-db
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,139 @@
    recipes = {}

    recipes["EEPROM (OpenOS)"]={fingerprint={id="OpenComputers:eeprom",dmg=0,max=64},qty=1,recipe={"EEPROM","Manual","","","","","","",""}}
    recipes["Graphics Card (T3)"]={fingerprint={id="OpenComputers:item",dmg=10,max=64},qty=1,recipe={"Microchip (T3)","ALU","RAM (T3)","","Card Base","","","",""}}
    recipes["Machine Block"]={fingerprint={id="IC2:blockMachine",dmg=0,max=64},qty=1,recipe={"Iron Plate","Iron Plate","Iron Plate","Iron Plate","","Iron Plate","Iron Plate","Iron Plate","Iron Plate"}}
    recipes["Microchip (T3)"]={fingerprint={id="OpenComputers:item",dmg=26,max=64},qty=1,recipe={"Diamond","","Diamond","Redstone","Transistor","Redstone","Diamond","","Diamond"}}
    recipes["Circuit"]={fingerprint={id="IC2:itemPartCircuit",dmg=0,max=64},qty=1,recipe={"Ins. Copper Cable","Ins. Copper Cable","Ins. Copper Cable","Redstone","Iron Plate","Redstone","Ins. Copper Cable","Ins. Copper Cable","Ins. Copper Cable"}}
    recipes["Paper"]={fingerprint={id="minecraft:paper",dmg=0,max=64},qty=3,recipe={"Canes","Canes","Canes","","","","","",""}}
    recipes["Server (T3)"]={fingerprint={id="OpenComputers:item",dmg=40,max=64},qty=1,recipe={"Obsidian","RAM (T3.5)","Obsidian","Microchip (T3)","Microchip (T3)","Microchip (T3)","Obsidian","PCB","Obsidian"}}
    recipes["String"]={fingerprint={id="minecraft:string",dmg=0,max=64},qty=1}
    recipes["Floppy Disk"]={fingerprint={id="OpenComputers:item",dmg=4,max=64},qty=1,recipe={"Iron Nugget","Lever","Iron Nugget","Paper","Disk Platter","Paper","Iron Nugget","Paper","Iron Nugget"}}
    recipes["Leather"]={fingerprint={id="minecraft:leather",dmg=0,max=64},qty=1}
    recipes["Adv. Machine Casing"]={fingerprint={id="IC2:blockMachine",dmg=12,max=64},qty=1,recipe={"Ref. Iron Plate","Carbon Plate","Ref. Iron Plate","Adv. Alloy","Machine Block","Adv. Alloy","Ref. Iron Plate","Carbon Plate","Ref. Iron Plate"}}
    recipes["Keyboard"]={fingerprint={id="OpenComputers:keyboard",dmg=0,max=64},qty=1,recipe={"Button Group","Button Group","Button Group","Button Group","Arrow Keys","Numeric Keypad","","",""}}
    recipes["Lapis"]={fingerprint={id="minecraft:dye",dmg=4,max=64},qty=1}
    recipes["Screen (T2)"]={fingerprint={id="OpenComputers:screen2",dmg=0,max=64},qty=1,recipe={"Gold","Rose Red","Gold","Cactus Green","Microchip (T2)","Glass","Gold","Lapis","Gold"}}
    recipes["ALU"]={fingerprint={id="OpenComputers:item",dmg=27,max=64},qty=1,recipe={"Iron Nugget","Redstone","Iron Nugget","Transistor","Microchip (T1)","Transistor","Iron Nugget","Transistor","Iron Nugget"}}
    recipes["Colorful Lamp"]={fingerprint={id="computronics:computronics.colorfulLamp",dmg=0,max=64},qty=1,recipe={"Iron","Glass","Iron","Glass","Glowstone","Glass","Iron","Glass","Iron"}}
    recipes["Duck Antenna"]={fingerprint={id="OpenPeripheral:generic",dmg=0,max=1},qty=1,recipe={"Redstone","Redstone","","Iron","Slimeball","","","",""}}
    recipes["Numeric Keypad"]={fingerprint={id="OpenComputers:item",dmg=22,max=64},qty=1,recipe={"Button","Button","Button","Button","Button","Button","Button","Button","Button"}}
    recipes["Fertilizer"]={fingerprint={id="Forestry:fertilizerCompound",dmg=0,max=64},qty=6,recipe={"","Sand","","","Apatite","","","Sand",""}}
    recipes["Clay"]={fingerprint={id="minecraft:clay",dmg=0,max=64},qty=1}
    recipes["Ref. Iron Plate"]={fingerprint={id="IC2:itemPlates",dmg=5,max=64},qty=1}
    recipes["Obsidian"]={fingerprint={id="minecraft:obsidian",dmg=0,max=64},qty=1}
    recipes["Diamond Block"]={fingerprint={id="minecraft:diamond_block",dmg=0,max=64},qty=1}
    recipes["Clock"]={fingerprint={id="minecraft:clock",dmg=0,max=1},qty=1,recipe={"","Gold","","Gold","Redstone","Gold","","Gold",""}}
    recipes["Diamond"]={fingerprint={id="minecraft:diamond",dmg=0,max=64},qty=9,recipe={"Diamond Block","","","","","","","",""}}
    recipes["Terminal Glasses"]={fingerprint={id="OpenPeripheral:glasses",dmg=0,max=1},qty=1,recipe={"Iron","Glowstone Block","Iron","Duck Antenna","Ender Pearl","Iron","Glass Pane","Redstone","Glass Pane"}}
    recipes["Piston"]={fingerprint={id="minecraft:piston",dmg=0,max=64},qty=1,recipe={"Planks","Planks","Planks","Cobble","Iron","Cobble","Cobble","Redstone","Cobble"}}recipes["Firework star [ST-g-b]"]={fingerprint={id="minecraft:firework_charge",dmg=0,max=64},qty=1,recipe={"Cactus Green","Gold Nugget","Gunpowder","Lapis","Glowstone","","","",""}}
    recipes["Manual"]={fingerprint={id="OpenComputers:item",dmg=98,max=64},qty=1,recipe={"Book","Microchip (T1)","","","","","","",""}}
    recipes["RAM (T3.5)"]={fingerprint={id="OpenComputers:item",dmg=39,max=64},qty=1,recipe={"Microchip (T3)","Microchip (T3)","Microchip (T3)","Microchip (T2)","PCB","Microchip (T2)","","",""}}
    recipes["Analyzer"]={fingerprint={id="OpenComputers:item",dmg=0,max=64},qty=1,recipe={"Redstone Torch","","","Transistor","Gold Nugget","","PCB","Gold Nugget",""}}
    recipes["Slimeball"]={fingerprint={id="minecraft:slime_ball",dmg=0,max=64},qty=1}
    recipes["Control Unit"]={fingerprint={id="OpenComputers:item",dmg=28,max=64},qty=1,recipe={"Gold Nugget","Redstone","Gold Nugget","Transistor","Clock","Transistor","Gold Nugget","Transistor","Gold Nugget"}}
    recipes["Stone"]={fingerprint={id="minecraft:stone",dmg=0,max=64},qty=1}
    recipes["Blaze Powder"]={fingerprint={id="minecraft:blaze_powder",dmg=0,max=64},qty=2,recipe={"Blaze Rod","","","","","","","",""}}
    recipes["Solar Generator Upgrade"]={fingerprint={id="OpenComputers:item",dmg=34,max=1},qty=1,recipe={"Glass","Glass","Glass","Microchip (T3)","Lapis Block","Microchip (T3)","Iron","PCB","Iron"}}
    recipes["Wooden Slab"]={fingerprint={id="minecraft:wooden_slab",dmg=0,max=64},qty=6,recipe={"Planks","Planks","Planks","","","","","",""}}
    recipes["Screen (T3)"]={fingerprint={id="OpenComputers:screen3",dmg=0,max=64},qty=1,recipe={"Obsidian","Glowstone","Obsidian","Glowstone","Microchip (T3)","Glass","Obsidian","Glowstone","Obsidian"}}
    recipes["Transistor"]={fingerprint={id="OpenComputers:item",dmg=23,max=64},qty=1,recipe={"Iron Nugget","Iron Nugget","Iron Nugget","Gold Nugget","Paper","Gold Nugget","","Redstone",""}}
    recipes["Gold"]={fingerprint={id="minecraft:gold_ingot",dmg=0,max=64},qty=9,recipe={"Gold Block","","","","","","","",""}}
    recipes["Book&Quill"]={fingerprint={id="minecraft:writable_book",dmg=0,max=1},qty=1,recipe={"Ink","Book","Feather","","","","","",""}}
    recipes["Internet Card"]={fingerprint={id="OpenComputers:item",dmg=44,max=64},qty=1,recipe={"Interweb","Microchip (T2)","Redstone Torch","","Card Base","Obsidian","","",""}}
    recipes["Energy Crystal"]={fingerprint={id="IC2:itemBatCrystal",dmg=27,max=64},qty=1}
    recipes["Adv. Alloy"]={fingerprint={id="IC2:itemPartAlloy",dmg=0,max=64},qty=1}
    recipes["Power Converter"]={fingerprint={id="OpenComputer:powerConverter",dmg=0,max=64},qty=1,recipe={"Iron","Cable","Iron","Gold","Microchip (T1)","Gold","Iron","PCB","Iron"}}
    recipes["Book"]={fingerprint={id="minecraft:book",dmg=0,max=64},qty=1,recipe={"Leather","Paper","","Paper","Paper","","","",""}}
    recipes["Gunpowder"]={fingerprint={id="minecraft:gunpowder",dmg=0,max=64},qty=1}
    recipes["Lapis Block"]={fingerprint={id="minecraft:lapis_block",dmg=0,max=64},qty=1}
    recipes["Floppy Disk (OpenOS)"]={fingerprint={id="OpenComputers:item",dmg=4,max=64},qty=1,recipe={"Floppy Disk","Manual","","","","","","",""}}
    recipes["EEPROM"]={fingerprint={id="OpenComputers:eeprom",dmg=0,max=64},qty=1,recipe={"Gold Nugget","Transistor","Gold Nugget","Paper","Microchip (T1)","Paper","Gold Nugget","Redstone Torch","Gold Nugget"}}
    recipes["MFE"]={fingerprint={id="IC2:blockElectric",dmg=1,max=64},qty=1,recipe={"Ins. Gold Cable","Energy Crystal","Ins. Gold Cable","Energy Crystal","Machine Block","Energy Crystal","Ins. Gold Cable","Energy Crystal","Ins. Gold Cable"}}
    recipes["Lapis Dust"]={fingerprint={id="IC2:itemDust",dmg=12,max=64},qty=1}
    recipes["Glowstone Block"]={fingerprint={id="minecraft:glowstone",dmg=0,max=64},qty=1,recipe={"Glowstone","Glowstone","","Glowstone","Glowstone","","","",""}}
    recipes["Tin"]={fingerprint={id="IC2:itemIngot",dmg=1,max=64},qty=1}
    recipes["Microchip (T1)"]={fingerprint={id="OpenComputers:item",dmg=24,max=64},qty=1,recipe={"Iron Nugget","","Iron Nugget","Redstone","Transistor","Redstone","Iron Nugget","","Iron Nugget"}}
    recipes["Bronze"]={fingerprint={id="Forestry:ingotBronze",dmg=0,max=64},qty=4,recipe={"Tin","Copper","","Copper","Copper","","","",""}}
    recipes["Emerald"]={fingerprint={id="minecraft:emerald",dmg=0,max=64},qty=9,recipe={"Emerald Block","","","","","","","",""}}
    recipes["RAM (T3)"]={fingerprint={id="OpenComputers:item",dmg=38,max=64},qty=1,recipe={"Microchip (T3)","Iron Nugget","Microchip (T3)","","PCB","","","",""}}
    recipes["Interweb"]={fingerprint={id="OpenComputers:item",dmg=48,max=64},qty=1,recipe={"String","String","String","String","Ender Pearl","String","String","String","String"}}
    recipes["Remote Terminal"]={fingerprint={id="OpenComputers:item",dmg=41,max=1},qty=1,recipe={"Iron Nugget","Solar Generator Upgrade","Iron Nugget","Microchip (T3)","Screen (T2)","Wireless Network Card","Iron Nugget","Keyboard","Iron Nugget"}}
    recipes["Log"]={fingerprint={id="minecraft:log",dmg=0,max=64},qty=1}
    recipes["Firework star [ST-g]"]={fingerprint={id="minecraft:firework_charge",dmg=0,max=64},qty=1,recipe={"Cactus Green","Gold Nugget","Gunpowder","","Glowstone","","","",""}}
    recipes["Microchip (T2)"]={fingerprint={id="OpenComputers:item",dmg=25,max=64},qty=1,recipe={"Gold Nugget","","Gold Nugget","Redstone","Transistor","Redstone","Gold Nugget","","Gold Nugget"}}
    recipes["Emerald Block"]={fingerprint={id="minecraft:emerald_block",dmg=0,max=64},qty=1}
    recipes["Ins. Gold Cable"]={fingerprint={id="IC2:itemCable",dmg=3,max=64},qty=1,recipe={"Rubber","Rubber","","Gold Cable","","","","",""}}
    recipes["Gold Cable"]={fingerprint={id="IC2:itemCable",dmg=2,max=64},qty=1}
    recipes["HDD (T3)"]={fingerprint={id="OpenComputers:item",dmg=7,max=64},qty=1,recipe={"Microchip (T3)","Disk Platter","Diamond","PCB","Disk Platter","Piston","Microchip (T3)","Disk Platter","Diamond"}}
    recipes["Lever"]={fingerprint={id="minecraft:lever",dmg=0,max=64},qty=1,recipe={"Stick","","","Cobble","","","","",""}}
    recipes["Blaze Rod"]={fingerprint={id="minecraft:blaze_rod",dmg=0,max=64},qty=1}
    recipes["Copper Cable"]={fingerprint={id="IC2:itemCable",dmg=1,max=64},qty=1}
    recipes["Sturdy Casing"]={fingerprint={id="Forestry:sturdyMachine",dmg=0,max=64},qty=1,recipe={"Bronze","Bronze","Bronze","Bronze","","Bronze","Bronze","Bronze","Bronze"}}
    recipes["Component Bus (T3)"]={fingerprint={id="OpenComputers:item",dmg=72,max=64},qty=1,recipe={"Emerald","Redstone","Emerald","Microchip (T3)","Control Unit","","Emerald","PCB","Emerald"}}
    recipes["Advanced Circuit"]={fingerprint={id="IC2:itemPartCircuitAdv",dmg=0,max=64},qty=1,recipe={"Redstone","Lapis","Redstone","Glowstone","Circuit","Glowstone","Redstone","Lapis","Redstone"}}
    recipes["Ink"]={fingerprint={id="minecraft:dye",dmg=0,max=64},qty=1}
    recipes["Button Group"]={fingerprint={id="OpenComputers:item",dmg=20,max=64},qty=1,recipe={"Button","Button","Button","Button","Button","","","",""}}
    recipes["Head"]={fingerprint={id="minecraft:skull",dmg=3,max=64},qty=1}
    recipes["Iron Nugget"]={fingerprint={id="ganysnether:ironNugget",dmg=0,max=64},qty=9,recipe={"Iron","","","","","","","",""}}
    recipes["Component Bus (T1)"]={fingerprint={id="OpenComputers:item",dmg=70,max=64},qty=1,recipe={"Iron Nugget","Redstone","Iron Nugget","Microchip (T1)","Control Unit","","Iron Nugget","PCB","Iron Nugget"}}
    recipes["Apatite"]={fingerprint={id="Forestry:apatite",dmg=0,max=64},qty=1}
    recipes["Relay"]={fingerprint={id="OpenComputers:relay",dmg=0,max=64},qty=1,recipe={"Iron","Cable","Iron","Cable","Network Card","Cable","Iron","PCB","Iron"}}
    recipes["MFSU"]={fingerprint={id="IC2:blockElectric",dmg=2,max=64},qty=1,recipe={"Lapotron","Advanced Circuit","Lapotron","Lapotron","MFE","Lapotron","Lapotron","Adv. Machine Casing","Lapotron"}}
    recipes["Glowstone"]={fingerprint={id="minecraft:glowstone_dust",dmg=0,max=64},qty=1}
    recipes["Hologram Projector (T2)"]={fingerprint={id="OpenComputers:hologram2",dmg=0,max=64},qty=1,recipe={"Microchip (T3)","Glass","Microchip (T3)","PCB","Diamond Block","PCB","Obsidian","Blaze Powder","Obsidian"}}
    recipes["Stick"]={fingerprint={id="minecraft:stick",dmg=0,max=64},qty=4,recipe={"Planks","","","Planks","","","","",""}}
    recipes["Redstone"]={fingerprint={id="minecraft:redstone",dmg=0,max=64},qty=9,recipe={"Redstone Block","","","","","","","",""}}
    recipes["Network Card"]={fingerprint={id="OpenComputers:item",dmg=11,max=1},qty=1,recipe={"Cable","Microchip (T1)","","","Card Base","","","",""}}
    recipes["Redstone Torch"]={fingerprint={id="minecraft:redstone_torch",dmg=0,max=64},qty=1,recipe={"","Redstone","","","Stick","","","",""}}
    recipes["Chest"]={fingerprint={id="minecraft:chest",dmg=0,max=64},qty=1,recipe={"Planks","Planks","Planks","Planks","","Planks","Planks","Planks","Planks"}}
    recipes["CPU (T3)"]={fingerprint={id="OpenComputers:item",dmg=43,max=64},qty=1,recipe={"Emerald","Redstone","Emerald","Microchip (T3)","Control Unit","Microchip (T3)","Emerald","ALU","Emerald"}}
    recipes["Feather"]={fingerprint={id="minecraft:feather",dmg=0,max=64},qty=1}
    recipes["Iron Plate"]={fingerprint={id="IC2:itemPlates",dmg=4,max=64},qty=1}
    recipes["Planks"]={fingerprint={id="minecraft:planks",dmg=0,max=64},qty=4,recipe={"Log","","","","","","","",""}}
    recipes["Capacitor"]={fingerprint={id="OpenComputers:capacitor",dmg=0,max=64},qty=1,recipe={"Iron","Transistor","Iron","Gold Nugget","Paper","Gold Nugget","Iron","PCB","Iron"}}
    recipes["Glass Pane"]={fingerprint={id="minecraft:glass_pane",dmg=0,max=64},qty=16,recipe={"Glass","Glass","Glass","Glass","Glass","Glass","","",""}}
    recipes["Nether Quartz Dust"]={fingerprint={id="appliedenergistics2:item.ItemMultiMaterial",dmg=3,max=64},qty=1}
    recipes["Cactus Green"]={fingerprint={id="minecraft:dye",dmg=2,max=64},qty=1}
    recipes["Component Bus (T2)"]={fingerprint={id="OpenComputers:item",dmg=71,max=64},qty=1,recipe={"Gold Nugget","Redstone","Gold Nugget","Microchip (T2)","Control Unit","","Gold Nugget","PCB","Gold Nugget"}}
    recipes["Rose Red"]={fingerprint={id="minecraft:dye",dmg=1,max=64},qty=1}
    recipes["Wireless Network Card"]={fingerprint={id="OpenComputers:item",dmg=13,max=64},qty=1,recipe={"Ender Pearl","Microchip (T2)","","","Card Base","","","",""}}
    recipes["Raw Circuit Board"]={fingerprint={id="OpenComputers:item",dmg=30,max=64},qty=1,recipe={"Clay","Cactus Green","","Gold Nugget","","","","",""}}
    recipes["Diamond Dust"]={fingerprint={id="IC2:itemDust2",dmg=1,max=64},qty=1}
    recipes["Copper"]={fingerprint={id="IC2:itemIngot",dmg=0,max=64},qty=1}
    recipes["Server Rack"]={fingerprint={id="OpenComputers:serverRack",dmg=0,max=64},qty=1,recipe={"Microchip (T2)","Wireless Network Card","Microchip (T2)","Iron Bars","Chest","Iron Bars","Relay","PCB","Power Distributor"}}
    recipes["Disk Platter"]={fingerprint={id="OpenComputers:item",dmg=19,max=64},qty=1,recipe={"","Iron Nugget","","Iron Nugget","","Iron Nugget","","Iron Nugget",""}}
    recipes["Cable"]={fingerprint={id="OpenComputers:cable",dmg=0,max=64},qty=4,recipe={"","Iron Nugget","","Iron Nugget","Redstone","Iron Nugget","","Iron Nugget",""}}
    recipes["Wool"]={fingerprint={id="minecraft:wool",dmg=0,max=64},qty=1,recipe={"String","String","","String","String","","","",""}}
    recipes["Ins. Copper Cable"]={fingerprint={id="IC2:itemCable",dmg=0,max=64},qty=1,recipe={"Copper Cable","Rubber","","","","","","",""}}
    recipes["Barrel"]={fingerprint={id="JABBA:barrel",dmg=0,max=64},qty=1,recipe={"Log","Wooden Slab","Log","Log","Chest","Log","Log","Log","Log"}}
    recipes["Hopper"]={fingerprint={id="minecraft:hopper",dmg=0,max=64},qty=1,recipe={"Iron","","Iron","Iron","Chest","Iron","","Iron",""}}
    recipes["Rubber"]={fingerprint={id="IC2:itemRubber",dmg=0,max=64},qty=1}
    recipes["Computer Case (T3)"]={fingerprint={id="OpenComputers:case3",dmg=0,max=64},qty=1,recipe={"Diamond","Microchip (T3)","Diamond","Iron Bars","Chest","Iron Bars","Diamond","PCB","Diamond"}}
    recipes["Cobble"]={fingerprint={id="minecraft:cobblestone",dmg=0,max=64},qty=1}
    recipes["Firework star [ST-b]"]={fingerprint={id="minecraft:firework_charge",dmg=0,max=64},qty=1,recipe={"Lapis","Gold Nugget","Gunpowder","","Glowstone","","","",""}}
    recipes["Sunflower"]={fingerprint={id="minecraft:double_plant",dmg=0,max=64},qty=1}
    recipes["Gold Block"]={fingerprint={id="minecraft:gold_block",dmg=0,max=64},qty=1}
    recipes["Arrow Keys"]={fingerprint={id="OpenComputers:item",dmg=21,max=64},qty=1,recipe={"","Button","","Button","Button","Button","","",""}}
    recipes["Canes"]={fingerprint={id="minecraft:reeds",dmg=0,max=64},qty=1}
    recipes["Quartz Glass"]={fingerprint={id="appliedenergistics2:tile.BlockQuartzGlass",dmg=0,max=64},qty=4,recipe={"Nether Quartz Dust","Glass","Nether Quartz Dust","Glass","Nether Quartz Dust","Glass","Nether Quartz Dust","Glass","Nether Quartz Dust"}}
    recipes["PCB"]={fingerprint={id="OpenComputers:item",dmg=32,max=64},qty=1}
    recipes["Lapotron"]={fingerprint={id="IC2:itemBatLamaCrystal",dmg=26,max=64},qty=1,recipe={"Lapis Dust","Advanced Circuit","Lapis Dust","Lapis Dust","Energy Crystal","Lapis Dust","Lapis Dust","Advanced Circuit","Lapis Dust"}}
    recipes["Iron Bars"]={fingerprint={id="minecraft:iron_bars",dmg=0,max=64},qty=16,recipe={"Iron","Iron","Iron","Iron","Iron","Iron","","",""}}
    recipes["Glass"]={fingerprint={id="minecraft:glass",dmg=0,max=64},qty=1}
    recipes["Adapter"]={fingerprint={id="OpenComputers:adapter",dmg=0,max=64},qty=1,recipe={"Iron","Cable","Iron","Cable","Microchip (T1)","Cable","Iron","PCB","Iron"}}
    recipes["Power Distributor"]={fingerprint={id="OpenComputers:powerDistributor",dmg=0,max=64},qty=1,recipe={"Iron","Gold","Iron","Cable","Microchip (T1)","Cable","Iron","PCB","Iron"}}
    recipes["Yellow Dye"]={fingerprint={id="minecraft:dye",dmg=11,max=64},qty=2,recipe={"Sunflower","","","","","","","",""}}
    recipes["Iron"]={fingerprint={id="minecraft:iron_ingot",dmg=0,max=64},qty=9,recipe={"Iron Block","","","","","","","",""}}
    recipes["Disk Drive"]={fingerprint={id="OpenComputers:diskDrive",dmg=0,max=64},qty=1,recipe={"Iron","Microchip (T1)","Iron","Piston","Stick","","Iron","PCB","Iron"}}
    recipes["Card Base"]={fingerprint={id="OpenComputers:item",dmg=33,max=64},qty=1,recipe={"Iron Nugget","","","Iron Nugget","PCB","","Iron Nugget","Gold Nugget",""}}
    recipes["Iron Block"]={fingerprint={id="minecraft:iron_block",dmg=0,max=64},qty=1}
    recipes["Gold Nugget"]={fingerprint={id="minecraft:gold_nugget",dmg=0,max=64},qty=9,recipe={"Gold","","","","","","","",""}}
    recipes["Sand"]={fingerprint={id="minecraft:sand",dmg=0,max=64},qty=1}
    recipes["Energium Dust"]={fingerprint={id="IC2:itemDust2",dmg=2,max=64},qty=9,recipe={"Redstone","Diamond Dust","Redstone","Diamond Dust","Redstone","Diamond Dust","Redstone","Diamond Dust","Redstone"}}
    recipes["Button"]={fingerprint={id="minecraft:stone_button",dmg=0,max=64},qty=1,recipe={"Stone","","","","","","","",""}}
    recipes["Charger"]={fingerprint={id="OpenComputers:charger",dmg=0,max=64},qty=1,recipe={"Iron","Gold","Iron","Capacitor","Microchip (T2)","Capacitor","Iron","PCB","Iron"}}
    recipes["Carbon Plate"]={fingerprint={id="IC2:itemPartCarbonPlate",dmg=0,max=64},qty=1}
    recipes["HDD (T1)"]={fingerprint={id="OpenComputers:item",dmg=5,max=64},qty=1,recipe={"Microchip (T1)","Disk Platter","Iron","PCB","Disk Platter","Piston","Microchip (T1)","Disk Platter","Iron"}}
    recipes["Ender Pearl"]={fingerprint={id="minecraft:ender_pearl",dmg=0,max=64},qty=1}
    recipes["Redstone Block"]={fingerprint={id="minecraft:redstone_block",dmg=0,max=64},qty=1}
    83 changes: 47 additions & 36 deletions pc-recipes.lua
    Original file line number Diff line number Diff line change
    @@ -59,22 +59,23 @@ local function saveAll()
    local temp = io.open(FILE, "w")
    temp:write("recipes = {}\n\n")
    for name, item in pairs(recipes) do
    temp:write("recipes[\"" .. name .. "\"] = {\n")
    temp:write(" [\"fingerprint\"] = {\n")
    temp:write(" [\"id\"] = \"" .. item.fingerprint.id .. "\",\n")
    temp:write(" [\"dmg\"] = " .. item.fingerprint.dmg .. "\n")
    temp:write(" },\n")
    temp:write("recipes[\"" .. name .. "\"]={")
    temp:write("fingerprint={")
    temp:write("id=\"" .. item.fingerprint.id .. "\",")
    temp:write("dmg=" .. item.fingerprint.dmg .. ",")
    temp:write("max=" .. (item.fingerprint.max or 64) .. "")
    temp:write("},")
    if item.recipe then
    temp:write(" [\"qty\"] = " .. item.qty .. ",\n")
    temp:write(" [\"recipe\"] = {\n")
    temp:write(" \"" .. item.recipe[1] .. "\", \"" .. item.recipe[2] .. "\", \"" .. item.recipe[3] .. "\",\n")
    temp:write(" \"" .. item.recipe[4] .. "\", \"" .. item.recipe[5] .. "\", \"" .. item.recipe[6] .. "\",\n")
    temp:write(" \"" .. item.recipe[7] .. "\", \"" .. item.recipe[8] .. "\", \"" .. item.recipe[9] .. "\"\n")
    temp:write(" }\n")
    temp:write("}\n\n")
    temp:write("qty=" .. item.qty .. ",")
    temp:write("recipe={")
    temp:write("\"" .. item.recipe[1] .. "\",\"" .. item.recipe[2] .. "\",\"" .. item.recipe[3] .. "\",")
    temp:write("\"" .. item.recipe[4] .. "\",\"" .. item.recipe[5] .. "\",\"" .. item.recipe[6] .. "\",")
    temp:write("\"" .. item.recipe[7] .. "\",\"" .. item.recipe[8] .. "\",\"" .. item.recipe[9] .. "\"")
    temp:write("}")
    temp:write("}\n")
    else
    temp:write(" [\"qty\"] = " .. item.qty .. "\n")
    temp:write("}\n\n")
    temp:write("qty=" .. item.qty)
    temp:write("}\n")
    end
    end
    temp:close()
    @@ -107,6 +108,7 @@ local function addRecipe(edit)
    print("Найден рецепт \"" .. name .. "\":")
    print(" ID: " .. recipes[name].fingerprint.id)
    print(" Meta: " .. recipes[name].fingerprint.dmg)
    print(" Стек: " .. (recipes[name].fingerprint.max or 64))
    print(" Количество: " .. recipes[name].qty)
    if recipes[name].recipe ~= nil then
    print(" Рецепт:")
    @@ -126,6 +128,8 @@ local function addRecipe(edit)
    local id = unicode.sub(term.read(), 1, -2)
    io.write("Meta: ")
    local dmg = unicode.sub(term.read(), 1, -2)
    io.write("Стэк: ")
    local stacksize = unicode.sub(term.read(), 1, -2)
    print("Нажмите [Enter], если хотите задать рецепт, и любую другую клавишу в противном случае")
    local makeRecipe = true
    local keyData = {event.pull("key_down")}
    @@ -151,8 +155,7 @@ local function addRecipe(edit)
    print("Слот #" .. i)
    print("(оставьте пустым для пропуска):")
    io.write(": ")
    item = term.read(history, nil, hint)
    table.insert(recipe, unicode.sub(item, 1, -2))
    item = term.read(history, nil, hint) table.insert(recipe, unicode.sub(item, 1, -2))
    print("Записано: " .. recipe[i] .. "\n")
    end
    end
    @@ -177,6 +180,7 @@ local function addRecipe(edit)
    print(" Имя: " .. name)
    print(" ID: " .. id)
    print(" Meta: " .. dmg)
    print(" Стек: " .. stacksize)
    print(" Количество: " .. qty)
    if recipe[1] ~= nil then
    print(" Рецепт:")
    @@ -192,20 +196,22 @@ local function addRecipe(edit)
    end
    if recipe[1] then
    recipes[name] = {
    ["fingerprint"] = {
    ["id"] = id,
    ["dmg"] = dmg
    fingerprint = {
    id = id,
    dmg = dmg,
    max = stacksize
    },
    ["qty"] = qty,
    ["recipe"] = recipe
    qty = qty,
    recipe = recipe
    }
    else
    recipes[name] = {
    ["fingerprint"] = {
    ["id"] = id,
    ["dmg"] = dmg
    fingerprint = {
    id = id,
    dmg = dmg,
    max = stacksize
    },
    ["qty"] = qty
    qty = qty
    }
    end
    print("Изменения применены. Не забудьте сохранить базу данных рецептов!")
    @@ -227,6 +233,7 @@ local function delRecipe()
    print("Найден рецепт \"" .. item .. "\":")
    print(" ID: " .. recipes[item].fingerprint.id)
    print(" Meta: " .. recipes[item].fingerprint.dmg)
    print(" Стэк: " .. (recipes[item].fingerprint.max or 64))
    print(" Количество: " .. recipes[item].qty)
    if recipes[item].recipe ~= nil then
    print(" Рецепт:")
    @@ -259,6 +266,7 @@ local function showRecipe()
    print("Найден рецепт \"" .. name .. "\":")
    print(" ID: " .. recipes[name].fingerprint.id)
    print(" Meta: " .. recipes[name].fingerprint.dmg)
    print(" Стэк: " .. (recipes[name].fingerprint.max or 64))
    print(" Количество: " .. recipes[name].qty)
    if recipes[name].recipe then
    print(" Рецепт:")
    @@ -277,7 +285,7 @@ local function showRecipe()
    end
    end

    local function scanRecipe()
    localfunction scanRecipe()
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    @@ -304,6 +312,7 @@ local function scanRecipe()
    print("")
    local id = recipe[10].name
    local meta = recipe[10].damage
    local max = recipes[10].maxSize
    local qty, rcp = 1, {}
    local makeRcp = false
    for i =1, 9, 1 do
    @@ -348,6 +357,7 @@ local function scanRecipe()
    print(" Имя: " .. name)
    print(" ID: " .. id)
    print(" Meta: " .. meta)
    print(" Стэк: " .. max)
    print(" Количество: " .. qty)
    if rcp[1] then
    print(" Рецепт:")
    @@ -360,24 +370,25 @@ local function scanRecipe()
    if apply == "y" or apply == "Y" or apply == "yes" or apply == "Yes" or apply == "YES" then
    if rcp[1] then
    recipes[name] = {
    ["fingerprint"] = {
    ["id"] = id,
    ["dmg"] = meta
    fingerprint = {id = id,
    dmg = meta,
    max = max
    },
    ["qty"] = qty,
    ["recipe"] = {
    qty = qty,
    recipe = {
    rcp[1], rcp[2], rcp[3],
    rcp[4], rcp[5], rcp[6],
    rcp[7], rcp[8], rcp[9]
    }
    }
    else
    recipes[name] = {
    ["fingerprint"] = {
    ["id"] = id,
    ["dmg"] = meta
    fingerprint = {
    id = id,
    dmg = meta,
    max = max
    },
    ["qty"] = qty
    qty = qty
    }
    end
    print("Изменения применены. Не забудьте сохранить базу данных!")
    @@ -405,7 +416,7 @@ while true do
    print(" [7] Сканирование рецепта")
    io.write("Выберите действие: ")
    mode = term.read()
    until tonumber(mode) ~= nil and tonumber(mode) < 8 and tonumber(mode) > -1
    until tonumber(mode) ~=nil and tonumber(mode) < 8 and tonumber(mode) > -1

    mode = tonumber(mode)

    60 changes: 45 additions & 15 deletions robot-autorun.lua
    Original file line number Diff line number Diff line change
    @@ -10,11 +10,20 @@ local modem = com.modem
    local craft = com.crafting
    local MAX = 15
    local facing = 0
    local DEBUG = false

    modem.open(PORT)

    local function maxn(tbl)
    max = 1
    for num, i in pairs(tbl) do
    max = num
    end
    return max
    end

    local function send(...)
    print(...)
    if DEBUG then print(" →: ", ...) end
    modem.broadcast(PORT, ...)
    end

    @@ -70,8 +79,7 @@ local function mvx(step, trn)
    turn(0)
    end
    if step > 0 then
    for i = 1, step, 1 do
    sfFw()
    for i = 1, step, 1 do sfFw()
    end
    elseif step < 0 then
    for i = 1, -step, 1 do
    @@ -115,7 +123,7 @@ local function list(slot, dir)
    fingerprint = {
    id = stack.name,
    dmg = stack.damage,
    nbt = stack.tag
    max = stack.maxSize
    },
    size = stack.size
    }
    @@ -125,16 +133,36 @@ local function list(slot, dir)
    return slots
    end

    local function take(slot, qty, dir)
    print("In `take`", slot, qty, dir)
    local function take(slot, qty, dir, item)
    if DEBUG then print("In `take`", slot, qty, dir, item) end
    dir = dir or 3
    stack = inv.getStackInSlot(dir, slot)
    if stack == nil then
    send(false, 0)
    return false
    end
    local success, sucked = inv.suckFromSlot(dir, slot, qty), stack.size
    send(success, sucked)
    if item ~= nil then
    item = srl.unserialize(item)
    if DEBUG then print("Compare: " .. stack.name .. "@" .. stack.damage .. " w/ " .. item.id .. "@" .. item.dmg) end
    if not (stack.name == item.id and stack.damage == item.dmg) then
    send(false, 0)
    return false
    end
    end
    a = {inv.suckFromSlot(dir, slot, qty)}
    if DEBUG then print(table.unpack(a)) end
    local sucked = stack.size
    send(a[1], sucked)
    end

    local function clear()
    for i = 1, 9, 1 do
    i = i + math.floor((i - 1) / 3)
    robot.select(i)
    robot.dropDown()
    end
    robot.select(8) -- drop contents of the output slot
    robot.dropDown()
    end

    local actions = {
    @@ -150,32 +178,34 @@ local actions = {
    d = {robot.down, false},
    sf = {function(newfacing) facing = newfacing end, true},
    li = {function(slot) send(srl.serialize(list(slot))) end, false},
    craft = {function() robot.select(8) craft.craft() robot.dropDown() end, false},
    craft = {function(qty) qty = qty or 64 robot.select(8) craft.craft(qty) robot.dropDown() end, false},
    sel = {function(slot) robot.select(slot) end, true},
    take = {take, true},
    lc = {function(slot) send(srl.serialize(list(slot, 0))) end, false}
    lc = {function(slot) send(srl.serialize(list(slot, 0))) end, false},
    clear = {clear, false}
    }

    while true do
    local data = {event.pull("modem_message")}
    if data[6] then
    ifdata[6] then
    local msg = {}
    local args = {}
    for i = 6, #data, 1 do
    table.insert(msg, data[i])
    msg[i - 5] = data[i]
    end
    for i = 7, #data, 1 do
    table.insert(args, data[i])
    args[i - 6] = data[i]
    end
    io.write("\t")
    print(table.unpack(msg))
    if actions[msg[1]] then
    if actions[msg[1]][2] == true and msg[2] then
    actions[msg[1]][1](table.unpack(args))
    actions[msg[1]][1](table.unpack(args, 1, maxn(args)))
    elseif actions[msg[1]][2] == false then
    actions[msg[1]][1]()
    end
    end
    end
    os.sleep(0.2)
    os.sleep(0.5)
    modem.broadcast(PORT, "done")
    end
    4 changes: 2 additions & 2 deletions robot-scan.lua
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,7 @@ local inv = com.inventory_controller
    local modem = com.modem
    local ser = require("serialization")
    ---

    print("Программа сканирования рецептов")
    print("Убедитесь, что принимающий компьютер готов")
    os.sleep(1)
    @@ -20,7 +20,7 @@ end
    table.insert(recipe, inv.getStackInInternalSlot(8))
    print(" [OK]")
    io.write("Передача данных...")

    local toSend = ser.serialize(recipe)
    modem.broadcast(PORT, toSend)
    print(" [OK]")
  9. Fingercomp created this gist Dec 24, 2015.
    518 changes: 518 additions & 0 deletions pc-craft.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,518 @@
    -- Крафтилка на сундуках --

    local FILE = "/usr/share/db"
    local PORT = 666
    local TECH_SLOTS = 3
    local X, Y, Z = 0, 0, 0
    local CHESTX, CHESTY = 1, 2
    local DEBUG = false
    ---===---
    local com = require("component")
    local modem = com.modem
    local event = require("event")
    local term = require("term")
    local gpu = com.gpu
    local unicode = require("unicode")
    local comp = require("computer")
    local srl = require("serialization").serialize
    local unsrl = require("serialization").unserialize

    local w, h = gpu.getResolution()
    local curx, cury = 1, 1
    modem.open(PORT)
    local stacks = {}

    local function send(...)
    modem.broadcast(PORT, ...)
    end

    local function sendW(...)
    send(...)
    local data
    repeat
    data={event.pull(5, "modem_message")}
    until data[1] and data[6] == "done"
    end

    local function get(...)
    send(...)
    local data
    repeat
    data = {event.pull(5, "modem_message")}
    until data[1]
    local done
    repeat
    done = {event.pull(5, "modem_message")}
    until done[1] and done[6] == "done"
    return data
    end

    local function drawPrbar(line, cur, max)
    local width = w - 7
    local oneperc = width / 100
    local curwidth = math.floor(cur / max * oneperc * 100)
    gpu.set(1, line, "|" .. string.rep(" ", width) .. "| " .. math.floor(cur / max * 100) .. "%")
    gpu.set(2, line, string.rep("", curwidth))
    end

    local function updateList(onlyCrafted, prbar)
    if not onlyCrafted then
    if prbar then gpu.fill(1, 1, w, h, " ") gpu.set(1, math.floor((h - 1) / 2), "Сбор данных с робота. Пожалуйста, подождите...") end
    local totalopers = CHESTX * CHESTY + 1
    local doneopers = 0
    if prbar then drawPrbar(math.ceil(h / 2), doneopers, totalopers) end
    stacks = {}
    sendW("t", 3)
    for i = 1, CHESTX, 1 do
    stacks[i] = {}
    for j = 1, CHESTY, 1 do
    stacks[i][j] = unsrl(get("li")[6])
    sendW("z", 1)
    doneopers = doneopers + 1
    if prbar then drawPrbar(math.ceil(h / 2), doneopers, totalopers) end
    end
    sendW("x", 2)
    sendW("z", -CHESTY)
    sendW("t", 3)
    end
    sendW("x", CHESTX * -2)
    doneopers = doneopers + 1
    if prbar then drawPrbar(math.ceil(h/ 2), doneopers, totalopers) end
    end
    stacks[0] = {}
    stacks[0][0] = {}
    stacks[0][0] = unsrl(get("lc")[6])
    end
    loadfile(FILE, _ENV, _ENV)()
    sendW("x", X)
    sendW("y", Y)
    sendW("z", Z)
    updateList(_, true)


    local function quit()
    return
    end

    local checkAvail -- Forward declaration

    local function centerY(text, line)
    local textDiv = math.floor(unicode.len(text) / 2)
    local widthDiv = math.floor(w / 2)
    gpu.set(widthDiv - textDiv - 1, line, text)
    end

    local function moveTo(i, j)
    moveX = (i - curx) * 2
    moveZ = (j - cury)
    if DEBUG then print("MT", i, j, "|", curx, cury, "=>", moveX, moveZ) end
    if moveX ~= 0 then
    sendW("x", moveX)
    end
    if moveZ ~= 0 then
    sendW("z", moveZ)
    end
    sendW("t", 3)
    curx, cury = i, j
    end


    local function pushItem(item, slot, qty)
    local itemPrint = item.fingerprint
    local rslot = slot + math.floor((slot - 1) / 3)
    sendW("sel", rslot)
    _, _, places = checkAvail(_, item)
    success = false
    run = 1
    while not success do
    if DEBUG then print("Push", run, rslot, qty, table.unpack(places[run])) end
    mtx, mtz, dir = places[run][1], places[run][2], 0
    if mtx == 0 and mtz == 0 then
    mtx, mtz = 1, 1
    else
    dir = nil
    end
    moveTo(mtx, mtz)
    cslot = places[run][3]
    if DEBUG then print("Push:1", cslot, qty, dir) end
    data = get("take", cslot, qty, dir)
    success = data[6]
    sucked = data[7] or 0
    if DEBUG then print("Push:got", success, sucked) end
    if sucked < qty then
    success = false
    qty = qty - sucked
    end
    run = run + 1
    end
    end

    local function getItem(itemName)
    return recipes[itemName]
    end

    checkAvail = function(itemName, item)
    if DEBUG then print(itemName, item) end
    local itemStack
    if item == nil then
    itemStack = getItem(itemName)
    else
    itemStack = item
    end
    local itemFP = itemStack.fingerprint
    local data = false
    local places = {}
    size = 0
    updateList(true)
    for i = 0, #stacks, 1 do
    for j = (i == 0 and 0 or 1), #stacks[i], 1 do
    if DEBUG then print("CA:S", i, j) end
    for slot, stackinfo in pairs(stacks[i][j]) do
    if stackinfo.fingerprint.id == itemFP.id and stackinfo.fingerprint.dmg == itemFP.dmg then
    data = {true, stackinfo}
    table.insert(places, {i, j, slot})
    size = size + stackinfo.size
    if DEBUG then print("CA", true, stackinfo, i, j, slot) end
    end
    end
    end
    end
    if data == false then
    if DEBUG then print("CA", false) end
    return false
    end
    table.insert(data, places)
    table.insert(data, size)
    return table.unpack(data)
    end

    local tree = {}

    local function smartInsert(item, order, qty, noCraft, combine)
    if DEBUG then print("SI", item, order, qty, noCraft, combine) end
    local new = true
    if combine then
    for i = 1, #tree, 1 do
    if tree[i].item.fingerprint.id == item.fingerprint.id and tree[i].item.fingerprint.dmg == item.fingerprint.dmg then
    tree[i].order = math.max(order, tree[i].order)
    tree[i].qty = tree[i].qty + qty
    new = false
    break
    end
    end
    end
    if new then
    if noCraft then
    table.insert(tree, {["item"] = item, ["order"] = order, ["qty"] = qty, ["noCraft"] = true})
    else
    table.insert(tree, {["item"] = item, ["order"] = order, ["qty"] = qty, ["noCraft"] = false})
    end
    end
    end

    local function buildTree(itemName, order, qty, itemStack, toCraft, combine)
    if DEBUG then print(itemName, order, qty, itemStack, toCraft, combine) end
    local item = {}
    if itemName ~= nil then
    item = getItem(itemName)
    elseif itemStack ~= nil then
    item = itemStack
    end
    if type(item.recipe) == "table" then
    for i = 1, 9, 1 do
    if item.recipe[i] ~= "" then
    if not checkAvail(item.recipe[i]) then
    buildTree(item.recipe[i], order + 1, math.ceil(qty / item.qty), nil, false, true)
    else
    smartInsert(getItem(item.recipe[i]), order + 1, math.ceil(qty / item.qty), true, true)
    end
    end
    end
    else
    if not checkAvail(itemName) then
    io.stderr:write("Отсутствует компонент крафта: " .. item.fingerprint.id .. "@" .. item.fingerprint.dmg .. "!")
    quit()
    os.exit()
    end
    end
    if toCraft == nil then toCraft = false end
    if combine == nil then combine = true end
    if DEBUG then print("TC", toCraft, combine) end
    smartInsert(item, order, qty, toCraft, combine)
    end

    local stack = {}

    local function checkTree()
    for i = 1, #tree, 1 do
    local stack = tree[i]
    if DEBUG then print("ID", stack.item.fingerprint.id, stack.item.fingerprint.dmg) end
    local avail, info, _, size = checkAvail(nil, stack.item)
    if DEBUG then print("AQ", avail, stack.qty, type(stack.qty)) end
    if stack.noCraft then
    if avail then
    if DEBUG then print("CS", info.size) end
    if stack.qty > size then
    if stack.item.recipe then
    buildTree(nil, stack.order + 1, stack.qty - info.size, stack.item, false, false)
    else
    io.stderr:write("[ERR] Недостаточно ресурсов: " .. stack.item.fingerprint.id .. "@" .. stack.item.fingerprint.dmg .. " (" .. size .. "/" .. stack.qty .. ")!")
    quit()
    os.exit()
    end
    end
    else
    if stack.item.recipe then
    if DEBUG then print("M", stack.qty) end
    buildTree(nil, stack.order + 1, stack.qty, stack.item, false, false)
    else
    io.stderr:write("[ERR] Отсутствие ресурсов: " .. stack.item.fingerprint.id .. "@" .. stack.item.fingerprint.dmg .. " (" .. stack.qty .. ")!")
    quit()
    os.exit()
    end
    end
    end
    end
    end

    local function craft()
    local stats = {}
    stats.crafted = 0
    stats.timeStart = comp.uptime()
    stats.timeStop = 0
    stats.treeLen = #tree
    local orderTree = {}
    for i = 1, #tree, 1 do
    local order = tree[i].order + 1
    if not orderTree[order] then
    orderTree[order] = {}
    end
    table.insert(orderTree[order], {["item"] = tree[i].item, ["qty"] = tree[i].qty, ["noCraft"] = tree[i].noCraft})
    end
    stats.maxOrder = #orderTree
    for i = #orderTree, 1, -1 do
    print("[INFO] [Craft] Обработка очереди " .. i)
    for j = 1, #orderTree[i], 1 do
    print("[INFO] [Craft] Обработка задачи " .. j)
    if orderTree[i][j].item.recipe then
    if not orderTree[i][j].noCraft then
    print("[INFO] [Craft] ID предмета в задаче: " .. orderTree[i][j].item.fingerprint.id .. "@" .. orderTree[i][j].item.fingerprint.dmg)
    iters = orderTree[i][j].qty
    craftSize = orderTree[i][j].item.qty
    riters = iters
    if DEBUG then print("RIters", riters) end
    runs = {}
    while true do
    if riters < 65 then
    table.insert(runs, math.ceil(riters / craftSize))
    break
    else
    table.insert(runs, math.ceil(64 / craftSize))
    end
    riters = riters - 64
    end
    if DEBUG then print("Runs", table.unpack(runs)) end
    for l = 1, #runs, 1 do
    print("[INFO] [Craft] Крафт #" .. l .. " (кол-во: " .. runs[l] .. ")")
    for k = 1, 9, 1 do
    if orderTree[i][j].item.recipe[k] ~= "" then
    pushItem(getItem(orderTree[i][j].item.recipe[k]), k, runs[l])
    end
    end
    moveTo(1, 1)
    sendW("craft")
    stats.crafted = stats.crafted + runs[l]
    end
    end
    end
    end
    end
    stats.timeStop = comp.uptime()
    return stats
    end

    sendW("clear")

    local listH = h - 1

    local function getNumber(min, max)
    repeat
    gpu.fill(1, h, w, 1, " ")
    term.setCursor(1, h)
    io.write("Предмет для крафта (0 для выхода): ")
    input = term.read(nil, false)
    if tonumber(input) == 0 then
    term.clear()
    term.setCursor(1, 1)
    quit()
    os.exit()
    end
    until tonumber(input) ~= nil and tonumber(input) <= max and tonumber(input) >= min
    return tonumber(input)
    end

    local names = {}

    for name, _ in pairs(recipes) do
    table.insert(names, name)
    end

    local pages = {}
    local onPage = listH * 2
    if #names > onPage then
    onPage = onPage - 1
    end
    local j = 1
    local page = {}
    while true do
    page = {}
    for i = 1, onPage, 1 do
    if names[j + i] then
    table.insert(page, {j + i - 1, names[j + i - 1]})
    else
    break
    end
    end
    table.insert(pages, page)
    if not names[j + onPage + 1] then break end
    j = j + onPage
    end

    local lines = {}

    local function list(page)
    term.clear()
    for i = 1, #pages[page], 1 do
    local item = pages[page][i]
    local nonCraftable = (recipes[item[2] ].recipe and "[*] " or "")
    if i > listH then
    gpu.set(w / 2, i - listH, "[" .. item[1] .. "] " .. nonCraftable .. item[2])
    else
    gpu.set(1, i, "[" .. item[1] .. "] " .. nonCraftable .. item[2])
    end
    end
    end

    local function drawNext(id)
    gpu.set(w / 2, listH, "[" .. id .. "] Next ->")
    end

    local page = 0
    local input = ""
    local nextId = 0
    local returnToBack = false

    repeat
    page = page + 1
    if page > #pages then
    page = 1
    end
    list(page)
    if onPage ~= listH * 2 then
    nextId = pages[page][#pages[page] ][1] + 1
    drawNext(nextId)
    input = getNumber(pages[page][1][1], pages[page][#pages[page] ][1] + 1)
    else
    input = getNumber(pages[1][1][1], pages[1][#pages[1] ][1])
    end
    until input ~= nextId

    gpu.setBackground(0xFFFFFF)
    gpu.setForeground(0x000000)

    local request, id, lineH, offset = "", 0, 0, 1
    for i = 1, #pages[page], 1 do
    if pages[page][i][1] == tonumber(input) then
    request = pages[page][i][2]
    id = i
    end
    end
    if id > listH then
    lineH = id - listH
    offset = w / 2
    else
    lineH = id
    end

    gpu.fill(offset, lineH, w / 2 - 2, 1, " ")
    gpu.set(offset, lineH, "[" .. input .. "] " .. request)

    gpu.setForeground(0xFFFFFF)
    gpu.setBackground(0x000000)

    local qty = 0
    repeat
    term.clearLine(h)
    term.setCursor(1, h)
    io.write("Выберите количество (0 для выхода): ")
    qty = term.read()
    until tonumber(qty) ~= nil

    if tonumber(qty) < 1 then
    term.clear()
    term.setCursor(1, 1)
    quit()
    os.exit()
    end

    qty = tonumber(qty)
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("ПЛАН КРАФТА", 1)
    print("[INFO] Составление плана...")
    buildTree(request, 0, qty)
    for i =1, #tree, 1 do
    if tree[i].noCraft then
    noCraft = "[X]"
    else
    noCraft = ""
    end
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
    end
    gpu.set(1, h, "Нажмите [Enter] для проверки дерева и старта крафта...")
    local keyData = {event.pull("key_down")}
    if keyData[1] == nil or keyData[3] ~= 13 then
    term.clear()
    term.setCursor(1, 1)
    quit()
    os.exit()
    end
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("ПЛАН КРАФТА (ПЕРЕПРОВЕРКА)", 1)
    print("[INFO] Проверка плана...")
    checkTree()
    for i = 1, #tree, 1 do
    if tree[i].noCraft then
    noCraft = "[X]"
    else
    noCraft = ""
    end
    print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
    end
    gpu.set(1, h, "Нажмите [Enter] для продолжения...")
    keyData = {event.pull("key_down")}
    if keyData[1] == nil or keyData[3] ~= 13 then
    term.clear()
    term.setCursor(1, 1)
    quit()
    os.exit()
    end
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("ЛОГ КРАФТА", 1)
    print("[ATTN] Пожалуйста, не изменяйте содержимое сундуков до завершения процесса крафта!")
    local stats = craft()
    print("")
    print("[INFO] [Stats] Статистика:")
    print("[INFO] [Stats] Всего крафтов: " .. stats.crafted)
    print("[INFO] [Stats] Время крафта: " .. stats.timeStop - stats.timeStart .. "s")
    print("[INFO] [Stats] Очередей всего: " .. stats.maxOrder)
    print("[INFO] [Stats] Длина дерева: " .. stats.treeLen .. "\n")
    gpu.set(1, h - 1, string.rep("-", w))
    centerY("КРАФТ ЗАВЕРШЁН", h - 1)
    term.setCursor(1, h)
    sendW("t", 0)
    431 changes: 431 additions & 0 deletions pc-recipes.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,431 @@
    local FILE = "/usr/share/db"
    local BACKUP = "/usr/share/dbback"
    local PORT = 666
    ---===---
    local com = require("component")
    local fs = require("filesystem")
    local term = require("term")
    local unicode = require("unicode")
    local event = require("event")
    local ser = require("serialization")
    local gpu = com.gpu
    local modem = com.modem
    local w,h = gpu.getResolution()
    ---===---
    modem.open(PORT)
    local items = {}
    if not fs.exists(FILE) then
    local temp = io.open(FILE, "w")
    temp:write("recipes = {}\n")
    temp:close()
    end

    local function hint(part)
    part = (part or "")
    local contains = {}
    for i = 1, #items, 1 do
    if unicode.sub(items[i], 1, #part) == part then
    table.insert(contains, items[i])
    end
    end
    if #contains == 0 then
    return {part}
    end
    return contains
    end

    local function updateList(noDB)
    if not noDB then
    dofile(FILE)
    end

    items = {}
    for i, _ in pairs(recipes) do
    table.insert(items, i)
    end
    end

    local function centerY(text, line)
    local textDiv = math.floor(unicode.len(text) / 2)
    local widthDiv = math.floor(w / 2)
    gpu.set(widthDiv - textDiv - 1, line, text)
    end

    local function saveAll()
    print("Создание резервной копии...")
    fs.remove(BACKUP)
    fs.copy(FILE, BACKUP)
    print("Сохранение...")
    local temp = io.open(FILE, "w")
    temp:write("recipes = {}\n\n")
    for name, item in pairs(recipes) do
    temp:write("recipes[\"" .. name .. "\"] = {\n")
    temp:write(" [\"fingerprint\"] = {\n")
    temp:write(" [\"id\"] = \"" .. item.fingerprint.id .. "\",\n")
    temp:write(" [\"dmg\"] = " .. item.fingerprint.dmg .. "\n")
    temp:write(" },\n")
    if item.recipe then
    temp:write(" [\"qty\"] = " .. item.qty .. ",\n")
    temp:write(" [\"recipe\"] = {\n")
    temp:write(" \"" .. item.recipe[1] .. "\", \"" .. item.recipe[2] .. "\", \"" .. item.recipe[3] .. "\",\n")
    temp:write(" \"" .. item.recipe[4] .. "\", \"" .. item.recipe[5] .. "\", \"" .. item.recipe[6] .. "\",\n")
    temp:write(" \"" .. item.recipe[7] .. "\", \"" .. item.recipe[8] .. "\", \"" .. item.recipe[9] .. "\"\n")
    temp:write(" }\n")
    temp:write("}\n\n")
    else
    temp:write(" [\"qty\"] = " .. item.qty .. "\n")
    temp:write("}\n\n")
    end
    end
    temp:close()
    print("Завершено!")
    os.sleep(1)
    end

    local function addRecipe(edit)
    term.clear()
    gpu.set(1, 1, string.rep("-", w))
    if not edit then
    centerY("ДОБАВЛЕНИЕ РЕЦЕПТА", 1)
    else
    centerY("ИЗМЕНЕНИЕ РЕЦЕПТА", 1)
    end
    term.setCursor(1, 2)
    io.write("Название рецепта: ")
    if edit then funcHint = hint end
    local name = unicode.sub(term.read(nil, nil, funcHint), 1, -2)
    local oldName, newName
    if recipes[name] ~= nil and not edit then
    print("Данное имя уже существует!")
    os.sleep(1)
    return
    elseif edit and recipes[name] == nil then
    print("Данного рецепта не существует!")
    os.sleep(1)
    return
    elseif recipes[name] ~= nil and edit then
    print("Найден рецепт \"" .. name .. "\":")
    print(" ID: " .. recipes[name].fingerprint.id)
    print(" Meta: " .. recipes[name].fingerprint.dmg)
    print(" Количество: " .. recipes[name].qty)
    if recipes[name].recipe ~= nil then
    print(" Рецепт:")
    for i = 1, 9, 1 do
    print(" [" .. i .. "] " .. recipes[name].recipe[i])
    end
    end
    io.write("\nНажмите [Enter] для изменения...")
    local keyData = {event.pull("key_down")}
    if keyData[1] == nil or keyData[3] ~= 13 then
    return
    end
    io.write("\nНовое имя (оставьте пустым для старого): ")
    newName = unicode.sub(term.read(), 1, -2)
    end
    io.write("ID: ")
    local id = unicode.sub(term.read(), 1, -2)
    io.write("Meta: ")
    local dmg = unicode.sub(term.read(), 1, -2)
    print("Нажмите [Enter], если хотите задать рецепт, и любую другую клавишу в противном случае")
    local makeRecipe = true
    local keyData = {event.pull("key_down")}
    if keyData[1] == nil or keyData[3] ~= 13 then
    makeRecipe = false
    end
    local qty = 1
    local recipe = {}
    local history = {}
    if makeRecipe then
    repeat
    term.clearLine()
    local _, y = term.getCursor()
    term.setCursor(1, y)
    io.write("Выходное количество: ")
    qty = unicode.sub(term.read(nil, false), 1, -2)
    until tonumber(qty) ~= nil and tonumber(qty) > 0
    print("")
    print("Этап создания рецепта")
    local item = ""
    for i = 1, 9, 1 do
    item = ""
    print("Слот #" .. i)
    print("(оставьте пустым для пропуска):")
    io.write(": ")
    item = term.read(history, nil, hint)
    table.insert(recipe, unicode.sub(item, 1, -2))
    print("Записано: " .. recipe[i] .. "\n")
    end
    end
    io.write("[ДАЛЕЕ ->]")
    repeat
    local keyData = {event.pull("key_down")}
    until keyData[1] ~= nil and keyData[3] == 13

    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("ПРИМЕНЕНИЕ ИЗМЕНЕНИЙ", 1)
    if not edit then
    print("Вы запросили добавить следующий рецепт:")
    else
    print("Вы запросили изменить рецепт так:")
    end
    if edit and newName ~= "" then
    oldName = name
    name = newName
    end
    print(" Имя: " .. name)
    print(" ID: " .. id)
    print(" Meta: " .. dmg)
    print(" Количество: " .. qty)
    if recipe[1] ~= nil then
    print(" Рецепт:")
    for i = 1, 9, 1 do
    print(" [" .. i .. "] " .. recipe[i])
    end
    end
    io.write("\nПрименить изменения? [y/N] ")
    local r = unicode.sub(term.read(), 1, -2)
    if r == "y" or r == "Y" or r == "yes" or r == "YES" then
    if edit and newName ~= "" then
    recipes[oldName] = nil
    end
    if recipe[1] then
    recipes[name] = {
    ["fingerprint"] = {
    ["id"] = id,
    ["dmg"] = dmg
    },
    ["qty"] = qty,
    ["recipe"] = recipe
    }
    else
    recipes[name] = {
    ["fingerprint"] = {
    ["id"] = id,
    ["dmg"] = dmg
    },
    ["qty"] = qty
    }
    end
    print("Изменения применены. Не забудьте сохранить базу данных рецептов!")
    else
    print("Изменения утеряны")
    end
    os.sleep(1)
    end

    local function delRecipe()
    updateList(true)
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("УДАЛЕНИЕ РЕЦЕПТА", 1)
    io.write("Введите имя рецепта для удаления: ")
    local item = unicode.sub(term.read(nil, nil, hint), 1, -2)
    if recipes[item] then
    print("Найден рецепт \"" .. item .. "\":")
    print(" ID: " .. recipes[item].fingerprint.id)
    print(" Meta: " .. recipes[item].fingerprint.dmg)
    print(" Количество: " .. recipes[item].qty)
    if recipes[item].recipe ~= nil then
    print(" Рецепт:")
    for i = 1, 9, 1 do
    print(" [" .. i .. "] " .. recipes[item].recipe[i])
    end
    end
    io.write("\nВы уверены, что хотите удалить данный рецепт? [y/N] ")
    local r = unicode.sub(term.read(), 1, -2)
    if r == "y" or r == "Y" or r == "yes" or r == "YES" then
    recipes[item] = nil
    print("Рецепт был удалён. Сохраните изменения для применения.")
    else
    print("Нет изменений.")
    end
    else
    print("Данный рецепт не найден!")
    end
    os.sleep(1)
    end

    local function showRecipe()
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("ПРОСМОТР РЕЦЕПТА", 1)
    io.write("Имя рецепта: ")
    local name = unicode.sub(term.read(nil, nil, hint), 1, -2)
    if recipes[name] then
    print("Найден рецепт \"" .. name .. "\":")
    print(" ID: " .. recipes[name].fingerprint.id)
    print(" Meta: " .. recipes[name].fingerprint.dmg)
    print(" Количество: " .. recipes[name].qty)
    if recipes[name].recipe then
    print(" Рецепт:")
    for i = 1, 9, 1 do
    print(" [" .. i .. "] " .. recipes[name].recipe[i])
    end
    end
    print("\nНажмите [Enter] для возврата...")
    local keyData
    repeat
    keyData = {event.pull("key_down")}
    until keyData[1] ~= nil and keyData[3] == 13
    else
    print("Этот рецепт не существует!")
    os.sleep(1)
    end
    end

    local function scanRecipe()
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("СКАНИРОВАНИЕ РЕЦЕПТА", 1)
    print("Включено прослушивание эфира. Ожидание сообщения от робота...")
    print("Нажмите [Enter] для возвращения")
    local recipe = {}
    repeat
    recipe = {event.pull(30)}
    until recipe[1] ~= nil and (recipe[1] == "key_down" or recipe[1] == "modem_message")
    if recipe[1] == "key_down" then
    return
    end
    recipe = recipe[6]
    recipe = ser.unserialize(recipe)
    local name = ""
    repeat
    term.clearLine()
    local _, y = term.getCursor()
    term.setCursor(1, y)
    io.write("Введите имя рецепта: ")
    name = unicode.sub(term.read(nil, false), 1, -2)
    until not recipes[name]
    print("")
    local id = recipe[10].name
    local meta = recipe[10].damage
    local qty, rcp = 1, {}
    local makeRcp = false
    for i =1, 9, 1 do
    if recipe[i] ~= "" then
    makeRcp = true
    break
    end
    end
    if makeRcp then
    repeat
    term.clearLine()
    local _, y = term.getCursor()
    term.setCursor(1, y)
    io.write("Выходное количество: ")
    qty = unicode.sub(term.read(nil, false), 1, -2)
    until tonumber(qty) and tonumber(qty) > 0
    print("")
    qty = tonumber(qty)
    for i = 1, 9, 1 do
    if recipe[i] ~= "" and recipe[i] ~= nil then
    for rcpName, stack in pairs(recipes) do
    -- print(rcpName, stack.fingerprint.id, stack.fingerprint.dmg, recipe[i].name, recipe[i].damage)
    if recipe[i].name == stack.fingerprint.id and recipe[i].damage == stack.fingerprint.dmg then
    rcp[i] = rcpName
    end
    end
    if rcp[i] == nil then
    io.stderr:write("Не найден компонент: " .. recipe[i].name .. "@" .. recipe[i].damage)
    os.sleep(1)
    return
    end
    else
    rcp[i] = ""
    end
    end
    end
    term.clear()
    term.setCursor(1, 2)
    gpu.set(1, 1, string.rep("-", w))
    centerY("ПРИМЕНЕНИЕ ИЗМЕНЕНИЙ", 1)
    print("Вы запросили добавить следующий рецепт:")
    print(" Имя: " .. name)
    print(" ID: " .. id)
    print(" Meta: " .. meta)
    print(" Количество: " .. qty)
    if rcp[1] then
    print(" Рецепт:")
    for i =1, 9, 1 do
    print(" [" .. i .. "] " .. rcp[i])
    end
    end
    io.write("Применить изменения? [y/N] ")
    local apply = unicode.sub(term.read(), 1, -2)
    if apply == "y" or apply == "Y" or apply == "yes" or apply == "Yes" or apply == "YES" then
    if rcp[1] then
    recipes[name] = {
    ["fingerprint"] = {
    ["id"] = id,
    ["dmg"] = meta
    },
    ["qty"] = qty,
    ["recipe"] = {
    rcp[1], rcp[2], rcp[3],
    rcp[4], rcp[5], rcp[6],
    rcp[7], rcp[8], rcp[9]
    }
    }
    else
    recipes[name] = {
    ["fingerprint"] = {
    ["id"] = id,
    ["dmg"] = meta
    },
    ["qty"] = qty
    }
    end
    print("Изменения применены. Не забудьте сохранить базу данных!")
    else
    print("Изменения утеряны.")
    end
    os.sleep(1)
    end

    updateList()
    ::main::
    while true do
    local mode = nil
    repeat
    term.clear()
    term.setCursor(1, 1)
    print("БД: " .. FILE)
    print(" [0] Выход")
    print(" [1] Добавление рецепта")
    print(" [2] Удаление рецепта")
    print(" [3] Изменение рецепта")
    print(" [4] Сохранение изменений")
    print(" [5] Обновить список")
    print(" [6] Показать информацию о рецепте")
    print(" [7] Сканирование рецепта")
    io.write("Выберите действие: ")
    mode = term.read()
    until tonumber(mode) ~= nil and tonumber(mode) < 8 and tonumber(mode) > -1

    mode = tonumber(mode)

    if mode == 0 then
    term.clear()
    term.setCursor(1, 1)
    os.exit()
    elseif mode == 1 then
    addRecipe()
    elseif mode == 2 then
    delRecipe()
    elseif mode == 3 then
    addRecipe(true)
    elseif mode == 4 then
    saveAll()
    elseif mode == 5 then
    updateList()
    elseif mode == 6 then
    showRecipe()
    elseif mode == 7 then
    scanRecipe()
    end
    end
    181 changes: 181 additions & 0 deletions robot-autorun.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,181 @@
    local PORT = 666

    local robot = require("robot")
    local com = require("component")
    local event = require("event")
    local srl = require("serialization")

    local inv = com.inventory_controller
    local modem = com.modem
    local craft = com.crafting
    local MAX = 15
    local facing = 0

    modem.open(PORT)

    local function send(...)
    print(...)
    modem.broadcast(PORT, ...)
    end

    local function sfFw()
    while not robot.forward() == true do
    os.sleep(1)
    end
    return true
    end

    local function sfBk()
    while not robot.back() == true do
    os.sleep(1)
    end
    return true
    end

    local function sfUp()
    while not robot.up() == true do
    os.sleep(1)
    end
    return true
    end

    local function sfDn()
    while not robot.down() == true do
    os.sleep(1)
    end
    return true
    end

    local function turn(dir)
    if dir == facing then
    return true
    end
    if math.abs(dir - facing) == 2 then
    robot.turnAround()
    end
    if facing == 0 and dir == 1 or facing == 2 and dir == 3 then
    robot.turnRight()
    elseif facing == 0 and dir == 3 or facing == 2 and dir == 1 then
    robot.turnLeft()
    elseif facing == 3 and dir == 0 or facing == 1 and dir == 2 then
    robot.turnRight()
    elseif facing == 3 and dir == 2 or facing == 1 and dir == 0 then
    robot.turnLeft()
    end
    facing = dir
    end

    local function mvx(step, trn)
    if not trn then
    turn(0)
    end
    if step > 0 then
    for i = 1, step, 1 do
    sfFw()
    end
    elseif step < 0 then
    for i = 1, -step, 1 do
    sfBk()
    end
    end
    end

    local function mvy(step)
    if step > 0 then
    turn(1)
    elseif step < 0 then
    turn(3)
    end
    mvx(math.abs(step), true)
    end

    local function mvz(step)
    if step > 0 then
    for i = 1, step, 1 do
    sfUp()
    end
    elseif step < 0 then
    for i = 1, -step, 1 do
    sfDn()
    end
    end
    end

    local function list(slot, dir)
    dir = dir or 3
    local slots = {}
    local inv_size = inv.getInventorySize(dir) or 54
    if slot and slot <= inv_size and slot > 0 then
    slots[slot] = inv.getStackInSlot(dir, slot)
    else
    for i = 1, inv_size, 1 do
    local stack = inv.getStackInSlot(dir, i)
    if stack then
    slots[i] = {
    fingerprint = {
    id = stack.name,
    dmg = stack.damage,
    nbt = stack.tag
    },
    size = stack.size
    }
    end
    end
    end
    return slots
    end

    local function take(slot, qty, dir)
    print("In `take`", slot, qty, dir)
    dir = dir or 3
    stack = inv.getStackInSlot(dir, slot)
    if stack == nil then
    send(false, 0)
    return false
    end
    local success, sucked = inv.suckFromSlot(dir, slot, qty), stack.size
    send(success, sucked)
    end

    local actions = {
    z = {mvz, true},
    x = {mvx, true},
    y = {mvy, true},
    l = {robot.turnLeft, false},
    r = {robot.turnRight, false},
    t = {turn, true},
    f = {robot.forward, false},
    b = {robot.back, false},
    u = {robot.up, false},
    d = {robot.down, false},
    sf = {function(newfacing) facing = newfacing end, true},
    li = {function(slot) send(srl.serialize(list(slot))) end, false},
    craft = {function() robot.select(8) craft.craft() robot.dropDown() end, false},
    sel = {function(slot) robot.select(slot) end, true},
    take = {take, true},
    lc = {function(slot) send(srl.serialize(list(slot, 0))) end, false}
    }

    while true do
    local data = {event.pull("modem_message")}
    if data[6] then
    local msg = {}
    local args = {}
    for i = 6, #data, 1 do
    table.insert(msg, data[i])
    end
    for i = 7, #data, 1 do
    table.insert(args, data[i])
    end
    print(table.unpack(msg))
    if actions[msg[1]] then
    if actions[msg[1]][2] == true and msg[2] then
    actions[msg[1]][1](table.unpack(args))
    elseif actions[msg[1]][2] == false then
    actions[msg[1]][1]()
    end
    end
    end
    os.sleep(0.2)
    modem.broadcast(PORT, "done")
    end
    26 changes: 26 additions & 0 deletions robot-scan.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,26 @@
    local PORT = 666
    ---
    local com = require("component")
    local inv = com.inventory_controller
    local modem = com.modem
    local ser = require("serialization")
    ---

    print("Программа сканирования рецептов")
    print("Убедитесь, что принимающий компьютер готов")
    os.sleep(1)
    io.write("\nСканирование...")
    local recipe = {}
    for i = 1, 9, 1 do
    local slot = i + (math.floor(i - 1) / 3)
    local stack = inv.getStackInInternalSlot(slot)
    if stack == nil then stack = "" end
    table.insert(recipe, stack)
    end
    table.insert(recipe, inv.getStackInInternalSlot(8))
    print(" [OK]")
    io.write("Передача данных...")

    local toSend = ser.serialize(recipe)
    modem.broadcast(PORT, toSend)
    print(" [OK]")