Advertisement
maz1lovo

Pc_obmen4

Jul 17th, 2025
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 19.04 KB | None | 0 0
  1. local img = [[
  2.  
  3.                                                        ██╗██╗    ██╗ █████╗ ██████╗ ██████╗     ██╗    ██╗
  4.                                                       ██╔╝██║    ██║██╔══██╗██╔══██╗██╔══██╗    ██║    ██║
  5.                                                      ██╔╝ ██║ █╗ ██║███████║██████╔╝██████╔╝    ██║ █╗ ██║
  6.                                                     ██╔╝  ██║███╗██║██╔══██║██╔══██╗██╔═══╝     ██║███╗██║
  7.                                                    ██╔╝   ╚███╔███╔╝██║  ██║██║  ██║██║         ╚███╔███╔╝
  8.                                                    ╚═╝     ╚══╝╚══╝ ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝          ╚══╝╚══╝
  9.                                                        
  10. ]]
  11.  
  12. local ore_dict = {
  13.     {
  14.         "Железная руда",
  15.         "Железный слиток",
  16.         take = {name = "minecraft:iron_ore", damage = 0},
  17.         give = {name = "minecraft:iron_ingot", damage = 0},
  18.         rate = {take = 4, give = 9}
  19.     },
  20.     {
  21.         "Золотая руда",
  22.         "Золотой слиток",
  23.         take = {name = "minecraft:gold_ore", damage = 0},
  24.         give = {name = "minecraft:gold_ingot", damage = 0},
  25.         rate = {take = 4, give = 9}
  26.     },
  27.     {
  28.         "Медная руда",
  29.         "Медный слиток",
  30.         take = {name = "IC2:blockOreCopper", damage = 0},
  31.         give = {name = "IC2:itemIngot", damage = 0},
  32.         rate = {take = 4, give = 9}
  33.     },
  34.     {
  35.         "Оловянная руда",
  36.         "Оловянный слиток",
  37.         take = {name = "IC2:blockOreTin", damage = 0},
  38.         give = {name = "IC2:itemIngot", damage = 1},
  39.         rate = {take = 4, give = 9}
  40.     },
  41.     {
  42.         "Свинцовая руда",
  43.         "Свинцовый слиток",
  44.         take = {name = "IC2:blockOreLead", damage = 0},
  45.         give = {name = "IC2:itemIngot", damage = 5},
  46.         rate = {take = 4, give = 8}
  47.     },
  48.     {
  49.         "Никелевая руда",
  50.         "Никелевый слиток",
  51.         take = {name = "ThermalFoundation:Ore", damage = 4},
  52.         give = {name = "ThermalFoundation:material", damage = 68},
  53.         rate = {take = 1, give = 2}
  54.     },
  55.     {
  56.         "Серебряная руда",
  57.         "Серебряный слиток",
  58.         take = {name = "ThermalFoundation:Ore", damage = 2},
  59.         give = {name = "IC2:itemIngot", damage = 6},
  60.         rate = {take = 4, give = 9}
  61.     },
  62. }
  63.  
  64. local unicode = require("unicode")
  65. local computer = require("computer")
  66. local com = require("component")
  67. local event = require("event")
  68. local internet = com.internet -- Добавляем интернет компонент
  69.  
  70. local gpu = com.gpu
  71. local me = com.me_interface -- Добавляем ME интерфейс
  72. local pim = com.pim -- Добавляем PIM (Player Interface)
  73. local w, h = gpu.maxResolution()
  74. local defBG, defFG = gpu.getBackground(), gpu.getForeground()
  75. gpu.setResolution(w, h)
  76.  
  77. -- Кэширование данных
  78. local cached = {
  79.     lastUpdate = 0,
  80.     updateInterval = 5,
  81.     oreQuantities = {}
  82. }
  83.  
  84. -- Статистика обменов
  85. local stats = {
  86.     exchanges = 0,
  87.     totalOre = 0,
  88.     totalIngots = 0
  89. }
  90.  
  91. -- Буфер экрана
  92. local screenBuffer = {}
  93.  
  94. -- Цветовые схемы
  95. local colors = {
  96.     info = 0x00ff00,
  97.     warning = 0xffff00,
  98.     error = 0xff0000,
  99.     border = 0x64fff2,
  100.     title = 0x00a400,
  101.     subtitle = 0xFFFFFF,
  102.     powered = 0x64fff2,
  103.     bg = 0x101010
  104. }
  105.  
  106. -- Анимация появления логотипа
  107. local function animateLogo(img, x, y, fore, delay, fast)
  108.     fore = fore or colors.title
  109.     local i = 0
  110.     local sleepTime = fast and 0.01 or (delay or 0.07)
  111.     for line in img:gmatch("([^\n]*)\n?") do
  112.         gpu.setForeground(fore)
  113.         gpu.set(x, y + i, line)
  114.         os.sleep(sleepTime)
  115.         i = i + 1
  116.     end
  117. end
  118.  
  119. -- Центрирование текста (перемещено выше)
  120. local function center(height, text, color)
  121.     gpu.setForeground(color)
  122.     local textLen = unicode.len(text)
  123.     local x = math.max(1, math.floor(w / 2 - textLen / 2))
  124.     gpu.set(x, height, text)
  125. end
  126.  
  127. -- Красивое приветствие
  128. local greetings = {
  129.     "Добро пожаловать в обменник!",
  130.     "Удачного обмена!",
  131.     "Пусть удача сопутствует вам!",
  132.     "Меняю руду на слитки — быстро и честно!",
  133.     "Powered by DemonAve"
  134. }
  135. local function showGreeting(player)
  136.     local greet = greetings[math.random(1, #greetings)]
  137.     if player then
  138.         center(h - 14, greet .. " | " .. player, colors.subtitle)
  139.     else
  140.         center(h - 14, greet, colors.subtitle)
  141.     end
  142. end
  143. local antiSpam = {
  144.     lastAction = 0,
  145.     cooldown = 1
  146. }
  147.  
  148. -- Таймер обновления данных
  149. local function shouldUpdate()
  150.     local currentTime = computer.uptime()
  151.     if currentTime - (cached.lastUpdate or 0) > (cached.updateInterval or 5) then
  152.         cached.lastUpdate = currentTime
  153.         return true
  154.     end
  155.     return false
  156. end
  157.  
  158.  
  159.  
  160.     -- Локальный вывод
  161. local function log(message, level, player)
  162.     local levels = {
  163.         info = 0x00ff00,
  164.         warning = 0xffff00,
  165.         error = 0xff0000
  166.     }
  167.     gpu.fill(1, h - 13, w, 1, " ") -- очищаем строку
  168.     center(h - 13, message, colors[level] or colors.subtitle)
  169. end
  170.  
  171. local function canProcess()
  172.     local current = computer.uptime()
  173.     if current - antiSpam.lastAction < antiSpam.cooldown then
  174.         return false
  175.     end
  176.     antiSpam.lastAction = current
  177.     return true
  178. end
  179.  
  180. local function bufferSet(x, y, text, fore, back)
  181.     local key = string.format("%d:%d", x, y)
  182.     local current = screenBuffer[key]
  183.     if not current or current.text ~= text or current.fore ~= fore or current.back ~= back then
  184.         screenBuffer[key] = {text = text, fore = fore, back = back}
  185.         gpu.setForeground(fore)
  186.         gpu.setBackground(back)
  187.         gpu.set(x, y, text)
  188.     end
  189. end
  190.  
  191. local function populateQty()
  192.     local totalOre = 0
  193.     for i, ore in pairs(ore_dict) do
  194.         local fingerprint = {id = ore.give.name, dmg = ore.give.damage}
  195.         local ok, item = pcall(me.getItemDetail, fingerprint)
  196.         if not ok or item == nil then
  197.             ore.qty = 0
  198.             ore.sizeOfStack = 64
  199.         else
  200.             local basicOk, basicItem = pcall(function() return item.basic() end)
  201.             if not basicOk or not basicItem then
  202.                 ore.qty = 0
  203.                 ore.sizeOfStack = 64
  204.             else
  205.                 ore.sizeOfStack = basicItem.max_size
  206.                 ore.qty = basicItem.qty
  207.                 totalOre = totalOre + basicItem.qty
  208.             end
  209.         end
  210.     end
  211.     return totalOre
  212. end
  213.  
  214. local function displayOres()
  215.     local line = 3
  216.     local colOre = math.floor(w * 0.04)
  217.     local colIngot = math.floor(w * 0.48)
  218.     local colTake = math.floor(w * 0.32)
  219.     local colGive = colTake + 8
  220.     local colArrow = colTake + 4
  221.     local colQty = math.floor(w * 0.88)
  222.     local colAvail = math.floor(w * 0.75)
  223.  
  224.     -- Верхняя рамка
  225.     gpu.setForeground(colors.border)
  226.     gpu.set(1, line - 1, "╔" .. string.rep("═", w - 2) .. "╗")
  227.     gpu.set(1, 3,"║")
  228.     gpu.set(1, 4,"║")
  229.     gpu.set(gpu.getResolution(), 3,"║")
  230.     gpu.set(gpu.getResolution(), 4,"║")
  231.     -- Заголовки таблицы (увеличенный текст)
  232.     gpu.setForeground(colors.title)
  233.     gpu.set(colOre + 2, line, "РУДА")
  234.     gpu.set(colTake + 2, line, "КУРС")
  235.     gpu.set(colIngot + 4, line, "СЛИТОК")
  236.     gpu.set(colAvail + 19, line, "ДОСТУПНО")
  237.     -- Вторая строка под заголовком можно использовать для подзаголовков или оставить пустой
  238.     gpu.set(colOre, line + 1, "")
  239.     gpu.set(colTake + 1, line + 1, "")
  240.     gpu.set(colIngot, line + 1, "")
  241.     gpu.set(colAvail, line + 1, "")
  242.     -- Разделитель под заголовком
  243.     gpu.setForeground(colors.border)
  244.     gpu.set(1, line + 2, "╠" .. string.rep("─", w - 2) .. "╣")
  245.  
  246.     local row = line + 3
  247.     for i, ore in ipairs(ore_dict) do
  248.         gpu.setForeground(colors.info)
  249.         gpu.set(colOre, row, ore[1] or "?")
  250.         gpu.set(colIngot, row, ore[2] or "?")
  251.         gpu.setForeground(0xFF00FF)
  252.         gpu.set(colTake, row, tostring((ore.rate and ore.rate.take) or "?"))
  253.         gpu.set(colGive, row, tostring((ore.rate and ore.rate.give) or "?"))
  254.         gpu.setForeground(colors.warning)
  255.         gpu.set(colArrow, row, "→")
  256.         gpu.setForeground(colors.info)
  257.         gpu.set(colQty, row, tostring(ore.qty or 0))
  258.         -- Боковые границы
  259.         gpu.setForeground(colors.border)
  260.         gpu.set(1, row, "║")
  261.         gpu.set(w, row, "║")
  262.         -- Полоса под каждой строкой, кроме последней
  263.         if i < #ore_dict then
  264.             gpu.setForeground(colors.border)
  265.             gpu.set(1, row + 1, "╟" .. string.rep("─", w - 2) .. "╢")
  266.             row = row + 2
  267.         else
  268.             row = row + 1
  269.         end
  270.     end
  271.     -- Нижняя рамка
  272.     gpu.setForeground(colors.border)
  273.     gpu.set(1, row, "╚" .. string.rep("═", w - 2) .. "╝")
  274. end
  275.  
  276. local function updateOres()
  277.     local totalOre = populateQty()
  278.     gpu.fill(1, 1, w, h - 16, " ")
  279.     if totalOre == 0 then
  280.         gpu.fill(1, 1, w, h - 15, " ")
  281.         center(h - 15, "Нет соединения с МЭ", 0xff0000)
  282.     else
  283.         displayOres()
  284.     end
  285. end
  286.  
  287. local function giveItemFromMe(item, dmg, amount)
  288.     local fingerprint = {id = item, dmg = dmg}
  289.     local ok, res = pcall(me.exportItem, fingerprint, "UP", amount)
  290.     if ok and res and res.size then
  291.         return res.size
  292.     else
  293.         return 0
  294.     end
  295. end
  296.  
  297. local function giveIngot(toGive, ore)
  298.     local totalGive = 0
  299.     local givePreIteration = 0
  300.     while totalGive < toGive do
  301.         if toGive - totalGive > 64 then
  302.             givePreIteration = ore.sizeOfStack
  303.         else
  304.             givePreIteration = toGive - totalGive
  305.         end
  306.  
  307.         local gived = giveItemFromMe(ore.give.name, ore.give.damage, givePreIteration)
  308.  
  309.         totalGive = totalGive + gived
  310.         if gived == 0 then
  311.             gpu.fill(1, h - 15, w, 2, " ")
  312.             center(h - 15, "Oсвободите место в инвентаре", 0xff0000)
  313.             center(h - 14, "Ожидаю выдать " .. tostring(toGive - totalGive) .. " " .. ore[2], 0xFFFFFF)
  314.             os.sleep(1)
  315.         end
  316.         gpu.fill(1, h - 15, 2, h, " ")
  317.     end
  318. end
  319.  
  320. local function exchangeOre(slot, ore, player)
  321.     local curSlot = pim.getStackInSlot(slot)
  322.     if curSlot == nil then
  323.         gpu.fill(1, h - 14, w, 1, " ")
  324.         center(h - 14, "Вы сошли с PIM, обмен прерван. (Не удалось прочесть слот)", 0xff0000)
  325.         log("Вы сошли с PIM, обмен прерван. (Не удалось прочесть слот)", "error", player)
  326.         os.sleep(0.5)
  327.         return
  328.     end
  329.     local userOreQty = curSlot.qty
  330.     local takeQty = userOreQty - (userOreQty % ore.rate.take)
  331.     local giveQty = userOreQty * ore.rate.give
  332.     if ore.qty < giveQty then
  333.         gpu.fill(1, h - 14, w, 1, " ")
  334.         center(h - 14, "Недостаточно слитков для обмена <" .. ore[1] .. ">", 0xff0000)
  335.         log("Недостаточно слитков для обмена <" .. ore[1] .. ">", "warning", player)
  336.         os.sleep(0.5)
  337.         return
  338.     end
  339.     -- Количество могло измениться..
  340.     local takedOre = pim.pushItem("DOWN", slot, takeQty)
  341.  
  342.     if takedOre == nil then
  343.         gpu.fill(1, h - 14, w, 1, " ")
  344.         center(h - 14, "Вы сошли с PIM, обмен прерван. (Не удалось извлечь руду)", 0xff0000)
  345.         log("Ошибка извлечения руды из PIM", "error", player)
  346.         os.sleep(0.5)
  347.     elseif takedOre == 0 then
  348.         gpu.fill(1, h - 14, w, 1, " ")
  349.         center(h - 14, "В выбраном слоте руды нет.. А была.. Хмм...", 0x505050)
  350.         log("В выбраном слоте руды нет", "warning", player)
  351.     else
  352.         local giveQty = (takedOre // ore.rate.take) * ore.rate.give
  353.         gpu.fill(1, h - 15, w, 2, " ")
  354.         -- Анимация движения стрелки
  355.         local baseText = "Меняю  " .. takedOre .. "  " .. ore[1] .. "  на  " .. giveQty .. "  " .. ore[2] .. "  "
  356.         local arrowFrames = {"→  ", " → ", "  →"}
  357.         for frame = 1, 6 do
  358.             local idx = (frame - 1) % #arrowFrames + 1
  359.             gpu.setForeground(frame % 2 == 1 and colors.warning or colors.info)
  360.             center(h - 14, baseText .. arrowFrames[idx], colors.subtitle)
  361.             os.sleep(0.12)
  362.         end
  363.         -- Добавляем статистику
  364.         stats.exchanges = stats.exchanges + 1
  365.         stats.totalOre = stats.totalOre + takedOre
  366.         stats.totalIngots = stats.totalIngots + giveQty
  367.         log("Обмен: " .. takedOre .. " " .. ore[1] .. " на " .. giveQty .. " " .. ore[2], "info", player)
  368.         giveIngot(giveQty, ore)
  369.         gpu.fill(1, h - 3, w, 1, " ")
  370.         center(h - 3, string.format("Всего обменов: %d | Руды: %d | Слитков: %d", stats.exchanges, stats.totalOre, stats.totalIngots), colors.info)
  371.     end
  372. end
  373.  
  374. local function checkInventory(player)
  375.     local size = pim.getInventorySize()
  376.     local ok, data = pcall(pim.getAllStacks, 0)
  377.     if not ok or not data then
  378.         gpu.fill(1, h - 14, w, 1, " ")
  379.         center(h - 14, "Ошибка получения инвентаря PIM", 0xff0000)
  380.         log("Ошибка получения инвентаря PIM", "error", player)
  381.         os.sleep(1)
  382.         return
  383.     end
  384.  
  385.     for slot = 1, size do
  386.         if data[slot] then
  387.             for i, ore in pairs(ore_dict) do
  388.                 if data[slot].id == ore.take.name and data[slot].dmg == ore.take.damage then
  389.                     exchangeOre(slot, ore, player)
  390.                 end
  391.             end
  392.         end
  393.     end
  394.  
  395.     updateOres()
  396.  
  397.     if pim.getInventoryName() ~= "pim" then
  398.         gpu.fill(1, h - 15, w, 2, " ")
  399.         center(h - 15, "Обмен окончен! Приходите ещё!", colors.subtitle)
  400.         log("Обмен окончен!", "info", player)
  401.         -- checkInventory() -- убираем рекурсию!
  402.     else
  403.         event.push("player_off", player)
  404.     end
  405. end
  406.  
  407. local eventHandlers = {
  408.     interrupted = function()
  409.         gpu.setBackground(defBG)
  410.         gpu.setForeground(defFG)
  411.         gpu.fill(1, 1, w, h, " ")
  412.         os.exit()
  413.         return true
  414.     end,
  415.  
  416.     player_on = function(...)
  417.         if not canProcess() then return end
  418.         local args = {...}
  419.         local player = args[1] or "Игрок"
  420.         gpu.fill(1, h - 15, w, 1, " ")
  421.         center(h - 15, "Приветствую, " .. player .. "! Начинаю обмен", colors.subtitle)
  422.         log("Игрок " .. player .. " начал обмен", "info", player)
  423.         updateOres()
  424.         checkInventory(player)
  425.     end,
  426.  
  427.     player_off = function(...)
  428.         if not canProcess() then return end
  429.         local args = {...}
  430.         local player = args[1] or "Игрок"
  431.         -- Очищаем экран и показываем только логотип
  432.         gpu.fill(1, 1, w, h, " ")
  433.         animateLogo(img, 1, h - 13, colors.title, 0.03)
  434.         -- Выводим статистику обменов
  435.         center(h - 3, string.format("Всего обменов: %d | Руды: %d | Слитков: %d", stats.exchanges, stats.totalOre, stats.totalIngots), colors.info)
  436.         center(h, "Powered by DemonAve", colors.powered)
  437.         log("Игрок " .. player .. " завершил обмен", "info", player)
  438.         -- Не вызываем updateOres, чтобы не перерисовывать таблицу на экране выхода
  439.     end
  440. }
  441.  
  442. function handleEvent(eventID, ...)
  443.     local handler = eventHandlers[eventID]
  444.     if handler then
  445.         return handler(...)
  446.     end
  447. end
  448.  
  449. function drawStat()
  450.     gpu.setForeground(0x444444)
  451.     gpu.set(
  452.         2,
  453.         h - 1,
  454.         string.format(
  455.             "RAM: %.1fkB / %.1fkB",
  456.             (computer.totalMemory() - computer.freeMemory()) / 1024,
  457.             computer.totalMemory() / 1024
  458.         )
  459.     )
  460. end
  461.  
  462.  
  463. local oreTimeFn = function()
  464.     updateOres()
  465.     -- Каджый 10 такт обновляем экран
  466.     for i = 1, 10 do
  467.         coroutine.yield()
  468.     end
  469. end
  470. local oreTimer = coroutine.create(oreTimeFn)
  471.  
  472. function draw_img(img, x, y, fore, back)
  473.     fore = fore or 0xffffff
  474.     back = back or 0x0
  475.     oldFG = gpu.getForeground()
  476.     gpu.setForeground(fore)
  477.     local i = 0
  478.     for line in img:gmatch("([^\n]*)\n?") do
  479.         gpu.set(x, y + i, line)
  480.         i = i + 1
  481.     end
  482.     gpu.setForeground(oldFG)
  483. end
  484. -- ...existing code...
  485.  
  486. -- Проверяем наличие необходимых компонентов
  487. if not me then
  488.     center(h - 15, "Ошибка: ME интерфейс не найден!", 0xff0000)
  489.     os.exit()
  490. end
  491.  
  492. if not pim then
  493.     center(h - 15, "Ошибка: PIM (Player Interface) не найден!", 0xff0000)
  494.     os.exit()
  495. end
  496.  
  497.  
  498. -- Стартовый экран с анимацией
  499. gpu.setBackground(colors.bg)
  500. gpu.fill(1, 1, w, h, " ")
  501. animateLogo(img, 1, h - 13, colors.title, 0.01, true)
  502. center(h - 15, "Для обмена встаньте на PIM и не сходите до окончания обмена", colors.subtitle)
  503. showGreeting()
  504. -- Выводим статистику обменов
  505. center(h - 3, string.format("Всего обменов: %d | Руды: %d | Слитков: %d", stats.exchanges, stats.totalOre, stats.totalIngots), colors.info)
  506. -- Powered by DemonAve (по центру)
  507. center(h, "Powered by DemonAve", colors.powered)
  508.  
  509.  
  510. while true do
  511.     drawStat()
  512.    
  513.     -- Очистка памяти при необходимости
  514.     if computer.freeMemory() < 1024 then
  515.         collectGarbage()
  516.     end
  517.    
  518.     -- Обновление данных по таймеру
  519.     if shouldUpdate() then
  520.         updateOres()
  521.     end
  522.    
  523.     local ev = {event.pull(1)}
  524.    
  525.     handleEvent(ev[1], table.unpack(ev, 2))
  526.    
  527.     if coroutine.status(oreTimer) == "dead" then
  528.         oreTimer = coroutine.create(oreTimeFn)
  529.     else
  530.         coroutine.resume(oreTimer)
  531.     end
  532. end
  533.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement