Стабилизация Энергетического ядра Draconic Evolution через OpenComputers
Для
Этот чегогайд этопоможет нужновам
Этанастроить программасистему предназначенаавтоматического дляконтроля тогоэнергии. Программа следит за тем, чтобы в ядре энергиихранилище всегда былооставался определенноенеобходимый количество энергиизапас для работы реакторов, чтобыпредотвращая вих ядреперегрев неили былоостановку. ееЕсли энергии слишком много или- слишкомкомпьютер мало.увеличивает Привыход, избыткеесли программа повышает выход из ядра, при недостачемало - понижаетограничивает или совсем отключает.
его.
Список1. компонентовНеобходимые компоненты
Компьютер (OpenComputers)
Ядро энергии
- Само ядро энергии (как его построить)
- Флаксовый гейт - 1шт
- Энергетический пилон - 1шт
- Криостабилизированная флаксовая труба - смотреть по ситуации
Первые2. шагиПодготовка и строительство
Обязательно первымПервым делом включаемвключите отображение границ чанков (F9)клавиша F9). Крайне важно строить всю конструкцию (ядро и длякомпьютер) удобствав выделяемпределах область.одного Дальше мы строим ядро энергии (лучше сразу 7го тира,чанка, чтобы потомизбежать неошибок перестраивать).при Главноезагрузке в одном чанке.мира. Инструкция по сборке ядра тут. Схематика тут.
Постройте Энергетическое ядро.
Скриншот ядра

Установка
СтавимУстановите всемониторы как(сеткой на3х2) скриншоте,и желательносистемный тожеблок. вНе одномзабудьте чанке.прикрепить клавиатуру к монитору.
Не
Скриншот установки пк и мониторов

Компоненты
Нюансы внутрисборки системного блока
Lua BIOS: Обычный чистый EEPROM нужно объединить в сетке крафта с "Руководством OpenComputers".
OpenOS: Обычную дискету также соедините с "Руководством OpenComputers", чтобы получить загрузочный диск с операционной системой.

Обратите
3. внимание что EEPROM должен быть именно (Lua BIOS), для этого создайте обычный EEPROM и в верстаке соедините его с Руководством OpenComputers.
Тоже самое касается и дискеты, делаем обычную дискету и соединяем ее с Руководством OpenComputers и мы получим дискету OpenOS (Operating System).
Подключение к ядрукомпонентов
Скриншот подключения к ядру

На что тут надо обратить внимание.
Настройка пилона и гейта
Энергетический пилон: Установите его и поставьте блок стекла сверху для активации. Нажмите ПКМ по синему ядру внутри пилона, чтобы стрелки были направлены наружу. Это режим отдачи энергии.
Флаксовый гейт: Ставьте строго по направлению потока. Фиолетовая сторона (вход) должна смотреть на негопилон, сверхуоранжевая стекло(выход) - в сторону ваших потребителей.
Соединение: Соедините пилон и он активируется, смотрите внимательно на стрелки пилона, они переключаются при нажатии ПКМ на маленькое синее ядро, стрелки ОБЯЗАТЕЛЬНО должны идти наружу, это значит что пилон работает на отдачу энергии.


Очень важно, следите за темСледите, чтобы ядро энергии не переполнялосьпереполнялось. энергией, иначеЕсли реакторам некуда будет деватьотдавать энергиюэнергию, произойдет критический перегрев и онивзрыв. взорвутся.ЕслиВыход этогейта будетдолжен проблемойбыть -подключен перепишук кодмощному ипотребителю добавлю(например, энергетическуюк мусорку,Генераторам чтобыматерии тудачерез сливаласьконвертер).

4. Настройка компьютерапрограммной части
ПослеВключите всехкомпьютер подключений мы заходимкнопкой в нашсистемном системный блок и нажимаем Включитьблоке.

Сначала мы видим загрузку, после чего у нас появляется вот такое окно

Для начала нам нужно установить
Установка ОС
После нашзагрузки компьютер,с длядискеты этоговведите впишите эту команду.Либо скопируйте и при помощи нажатия колесика мыши вставьте ее.команду:
install

ДальшеНажимайте Enter, подтверждая установку. В конце система предложит перезагрузку - снова нажмите Enter и начнется установка ОС. После завершения установки программа предложит перезагрузить ПК, опять нажмите Enter..

Безопасность и автозапуск
После перезагрузки нам нужно вписать в первую очередьДобавьте себя в администраторысписок ПКадминистраторов и(команда только потом тех кто будет им пользоваться помимо вас при помощи этой команды
Чувствителенчувствительна к регистру, если у игрока ник DesOope то и в команде нужно писать DesOope, а не desoope.регистру):
useradd ник

Это мы делали для того чтобы ПК могли пользоваться только вписанные в него пользователи.
ПослеНастройте тогоавтозапуск какпрограммы мыпри всехвключении добавили мы пишем такую командуПК:
edit .shrc
и дописываем в самом конце такую строку
gate.lua

И нажимаем Ctrl + S (сохранить) и Ctrl + W (закрыть).
Это
Создание нужно чтобы программа запускалась автоматически после перезагрузки.кода
Дальше создаемСоздайте файл gate.luaпрограммы:
edit gate.lua
У нас открывается окно для ввода кода, мы вписываем туда этотВставьте код. Код очень длинный, вставляйте его частями (вставлять надо по 250 строкстрок) из-за ограничений вставкибуфера кода)обмена.
Код
local component = require("component")
local event = require("event")
local computer = require("computer")
local unicode = require("unicode")
local term = require("term")
local keyboard = require("keyboard")
local gpu = component.gpu
--------------------------------------------------------------------------------
-- [КОНФИГУРАЦИЯ]
--------------------------------------------------------------------------------
local CFG = {
targetEnergy = 1000 * 10^9, -- Цель: 1 T RF
aggressiveness = 0.03, -- Плавность реакции стабилизации
-- Настройки кнопок
btnStep = 10^9, -- Шаг (1B)
btnStepCtrl = 10 * 10^9, -- Шаг с Ctrl (10B)
btnStepShift = 100 * 10^9 -- Шаг с Shift (100B)
}
local COLORS = {
bg = 0x111111, tileBg = 0x222222, tileHeader = 0x333333,
text = 0xEEEEEE, label = 0x999999,
good = 0x55FF55, warn = 0xFFAA00, bad = 0xFF5555,
energy = 0x00AAFF, sat = 0xFFAA00, fuel = 0xFFFF55,
btn = 0x444444, btnActive = 0x006699,
graphLine = 0x444444,
black = 0x000000
}
-- Проверка компонентов
if not component.isAvailable("draconic_rf_storage") then
print("ОШИБКА: Нет ядра (draconic_rf_storage)!")
os.exit()
end
if not component.isAvailable("flux_gate") then
print("ОШИБКА: Нет гейта (flux_gate)!")
os.exit()
end
local rfStorage = component.draconic_rf_storage
local fluxGate = component.flux_gate
local W, H = gpu.maxResolution()
gpu.setResolution(W, H)
--------------------------------------------------------------------------------
-- [ПЕРЕМЕННЫЕ И РАСЧЕТ МАКЕТА]
--------------------------------------------------------------------------------
local running = true
local buttons = {}
-- === НАСТРОЙКА СИММЕТРИИ ===
local M = 2 -- Отступ (Margin) со всех сторон
local panelH = 9 -- Высота верхних панелей
-- Расчет координат
local totalW = W - (M * 3)
local panelW = math.floor(totalW / 2)
-- Левая панель
local x1 = M
local y1 = M
-- Правая панель
local x2 = x1 + panelW + M
local y2 = M
-- График
local graphX = M
local graphY = y1 + panelH + 1
local graphW = W - (M * 2)
local graphH = H - graphY - M - 2
local energyHistory = {}
for i = 1, graphW do energyHistory[i] = 0 end
local maxCoreCapacity = rfStorage.getMaxEnergyStored()
-- Фильтр (Плавность)
local filVal = 0
local function expRunningAvg(newVal)
if math.abs(newVal - filVal) > 10^15 then filVal = newVal end
filVal = filVal + ((newVal - filVal) * 0.05)
return filVal
end
--------------------------------------------------------------------------------
-- [ГРАФИКА - ФУНКЦИИ]
--------------------------------------------------------------------------------
local function rect(x, y, w, h, col)
gpu.setBackground(col)
gpu.fill(x, y, w, h, " ")
end
local function text(x, y, str, fg, bg)
if bg then gpu.setBackground(bg) end
gpu.setForeground(fg)
gpu.set(x, y, str)
end
local function center(x, y, w, str, fg, bg)
if bg then gpu.setBackground(bg) end
gpu.fill(x, y, w, 1, " ")
local px = x + math.floor((w - unicode.len(str))/2)
if fg then gpu.setForeground(fg) end
gpu.set(px, y, str)
end
-- ВНИМАНИЕ: Эта функция очищает всю строку под собой.
local function textRight(x, y, w, str, fg, bg)
if bg then gpu.setBackground(bg) end
gpu.fill(x, y, w, 1, " ")
local len = unicode.len(str)
local px = x + w - len
if fg then gpu.setForeground(fg) end
gpu.set(px, y, str)
end
local function fmt(num)
if math.abs(num) >= 10^12 then return string.format("%.3f T", num/10^12)
elseif math.abs(num) >= 10^9 then return string.format("%.3f B", num/10^9)
elseif math.abs(num) >= 10^6 then return string.format("%.3f M", num/10^6)
elseif math.abs(num) >= 10^3 then return string.format("%.3f K", num/10^3)
else return string.format("%d", math.floor(num)) end
end
local function progressBar(x, y, w, pct, colBar, colBg)
rect(x, y, w, 1, colBg)
local barW = math.floor(w * (pct/100))
if barW > w then barW = w end
if barW > 0 then rect(x, y, barW, 1, colBar) end
end
local function btn(id, x, y, w, h, str, bg, fg)
rect(x, y, w, h, bg)
center(x, y + math.floor(h/2), w, str, fg or COLORS.text, bg)
buttons[id] = {x=x, y=y, w=w, h=h}
end
--------------------------------------------------------------------------------
-- [ИНТЕРФЕЙС]
--------------------------------------------------------------------------------
local function drawStaticInterface()
gpu.setBackground(COLORS.bg)
term.clear()
-- Левая панель
rect(x1, y1, panelW, panelH, COLORS.tileBg)
rect(x1, y1, panelW, 1, COLORS.tileHeader)
center(x1, y1, panelW, "СОСТОЯНИЕ ЯДРА", COLORS.text, COLORS.tileHeader)
text(x1+2, y1+2, "НАКОПЛЕНО:", COLORS.label, COLORS.tileBg)
text(x1+2, y1+4, "ЦЕЛЬ СТАБ.:", COLORS.label, COLORS.tileBg)
-- Правая панель
rect(x2, y2, panelW, panelH, COLORS.tileBg)
rect(x2, y2, panelW, 1, COLORS.tileHeader)
center(x2, y2, panelW, "ЭНЕРГИЯ", COLORS.text, COLORS.tileHeader)
text(x2+2, y2+2, "ТЕКУЩИЙ ПОТОК:", COLORS.label, COLORS.tileBg)
text(x2+2, y2+4, "ВЫХОД ГЕЙТА:", COLORS.label, COLORS.tileBg)
-- График
rect(graphX, graphY, graphW, 1, COLORS.tileHeader)
center(graphX, graphY, graphW, " ГРАФИК ПОТОКА ", COLORS.label, COLORS.tileHeader)
rect(graphX, graphY+1, graphW, graphH, COLORS.bg)
-- Подвал
local footerY = H - 1
btn("exit", M, footerY, 10, 1, "ВЫХОД", COLORS.bad)
-- Кредиты
local crX = W - 32
local crY = H - 3
text(crX, crY, "Разработчик: DesOope", COLORS.label, COLORS.bg)
text(crX, crY+1, "Проект: McSkill", COLORS.label, COLORS.bg)
text(crX, crY+2, "Сервер: HitechClassic 1.7.10", COLORS.label, COLORS.bg)
end
local function drawGraph(delta)
table.insert(energyHistory, delta)
while #energyHistory > graphW do table.remove(energyHistory, 1) end
local gTopY = graphY + 1
local gBottomY = graphY + graphH
local midY = gTopY + math.floor(graphH/2)
if graphH < 2 then return end
local maxVal = 1
for _, v in ipairs(energyHistory) do
if math.abs(v) > maxVal then maxVal = math.abs(v) end
end
for i = 1, graphW do
local val = energyHistory[i] or 0
local x = graphX + i - 1
local h = 0
if math.abs(val) > 0 then
h = math.ceil( (math.abs(val) / maxVal) * (graphH/2) )
if h > (graphH/2) then h = math.floor(graphH/2) end
end
local barTop, barBottom
local color
if val > 0 then
barBottom = midY + 1
barTop = barBottom - h
if barTop < gTopY then barTop = gTopY end
color = COLORS.good
elseif val < 0 then
barTop = midY + 1
barBottom = barTop + h
if barBottom > gBottomY then barBottom = gBottomY end
color = COLORS.bad
else
barTop = midY
barBottom = midY + 1
color = COLORS.bg
end
if barTop > gTopY then
gpu.setBackground(COLORS.bg)
gpu.fill(x, gTopY, 1, barTop - gTopY, " ")
end
local barH = barBottom - barTop
if val ~= 0 and barH > 0 then
gpu.setBackground(color)
gpu.fill(x, barTop, 1, barH, " ")
elseif val == 0 then
gpu.setBackground(COLORS.bg)
gpu.setForeground(COLORS.graphLine)
gpu.set(x, midY, "─")
end
if barBottom < gBottomY then
gpu.setBackground(COLORS.bg)
local clearH = gBottomY - barBottom + 1
gpu.fill(x, barBottom, 1, clearH, " ")
end
end
end
local function updateLiveDisplay(stored, target, delta, gateFlow)
local valWidth = 16
local valX = x1 + panelW - valWidth - 2
-- === ЛЕВАЯ ПАНЕЛЬ ===
center(valX, y1+2, valWidth, fmt(stored).." RF", COLORS.energy, COLORS.tileBg)
center(valX, y1+4, valWidth, fmt(target).." RF", COLORS.warn, COLORS.tileBg)
local btnW = 3
local btnPlusX = valX - btnW - 1
btn("inc", btnPlusX, y1+4, btnW, 1, "+", COLORS.btn)
local btnMinusX = btnPlusX - btnW - 1
btn("dec", btnMinusX, y1+4, btnW, 1, "-", COLORS.btn)
local maxPct = (stored / maxCoreCapacity) * 100
if maxPct > 100 then maxPct = 100 end
local barX = x1 + 2
local barW = panelW - 4
center(barX, y1+6, barW, string.format("%.2f%% (от макс. объема)", maxPct), COLORS.text, COLORS.tileBg)
text(barX, y1+6, "0%", COLORS.label)
local str100 = "100%"
local x100 = barX + barW - unicode.len(str100)
text(x100, y1+6, str100, COLORS.label)
progressBar(barX, y1+7, barW, maxPct, COLORS.energy, 0x111111)
-- === ПРАВАЯ ПАНЕЛЬ ===
local valX2 = x2 + panelW - valWidth - 2
local dColor = COLORS.text
local sign = ""
if delta > 0 then dColor = COLORS.good; sign = "+"
elseif delta < 0 then dColor = COLORS.bad; sign = "" end
center(valX2, y2+2, valWidth, sign..fmt(delta).." RF/t", dColor, COLORS.tileBg)
center(valX2, y2+4, valWidth, fmt(gateFlow).." RF/t", COLORS.text, COLORS.tileBg)
-- === БОЛЬШОЙ СТАТУС БАР (ВНИЗУ) ===
local statusStr = ""
local statusBg = COLORS.btn
local statusFg = COLORS.black
-- НОВАЯ ЛОГИКА СТАТУСОВ
if math.abs(stored - target) < 10^9 then
-- Энергия в норме (равна цели)
statusStr = "СТАБИЛЬНО"
statusBg = COLORS.good
else
if stored < target then
-- Нехватка энергии
if delta > 0 then
-- Но она растет = Хорошо
statusStr = "ВОСПОЛНЕНИЕ"
statusBg = COLORS.energy -- Синий
else
-- Она падает = Плохо
statusStr = "ВНИМАНИЕ: РАЗРЯД"
statusBg = COLORS.bad -- Красный
statusFg = 0xFFFFFF
end
else
-- Избыток энергии
if delta < 0 then
-- Она падает (возвращается к цели) = Хорошо
statusStr = "СБРОС ИЗЛИШКОВ"
statusBg = COLORS.warn -- Оранжевый
else
-- Она растет дальше = Плохо
statusStr = "КРИТИЧЕСКОЕ ПЕРЕПОЛНЕНИЕ"
statusBg = COLORS.bad -- Красный
statusFg = 0xFFFFFF
end
end
end
local stX = x2 + 2
local stW = panelW - 4
local stY = y2 + 6
local stH = 3
gpu.setBackground(statusBg)
gpu.fill(stX, stY, stW, stH, " ")
center(stX, stY + 1, stW, statusStr, statusFg, statusBg)
drawGraph(delta)
end
local function handleTouch(x, y)
for id, b in pairs(buttons) do
if x >= b.x and x < b.x + b.w and y >= b.y and y < b.y + b.h then
if id == "exit" then
running = false
elseif id == "inc" or id == "dec" then
local step = CFG.btnStep
if keyboard.isControlDown() then step = CFG.btnStepCtrl
elseif keyboard.isShiftDown() then step = CFG.btnStepShift end
if id == "dec" then CFG.targetEnergy = CFG.targetEnergy - step end
if id == "inc" then CFG.targetEnergy = CFG.targetEnergy + step end
if CFG.targetEnergy < 0 then CFG.targetEnergy = 0 end
computer.beep(1000, 0.05)
rect(b.x, b.y, b.w, b.h, COLORS.good)
os.sleep(0.05)
rect(b.x, b.y, b.w, b.h, COLORS.btn)
end
end
end
end
--------------------------------------------------------------------------------
-- [ГЛАВНЫЙ ЦИКЛ]
--------------------------------------------------------------------------------
drawStaticInterface()
local prevTime = computer.uptime()
local prevEnergy = rfStorage.getEnergyStored()
while running do
local nowTime = computer.uptime()
local dt = nowTime - prevTime
if dt < 0.2 then
os.sleep(0.2)
nowTime = computer.uptime()
dt = nowTime - prevTime
end
local nowEnergy = rfStorage.getEnergyStored()
local rawDiff = (nowEnergy - prevEnergy) / (dt * 20)
local smoothedDiff = expRunningAvg(rawDiff)
local currentGate = fluxGate.getFlow()
local errorVal = nowEnergy - CFG.targetEnergy
local correction = errorVal * CFG.aggressiveness
local newGate = currentGate + smoothedDiff + correction
if newGate < 0 then newGate = 0 end
if math.abs(newGate - currentGate) > 500 then
fluxGate.setSignalLowFlow(math.floor(newGate))
end
updateLiveDisplay(nowEnergy, CFG.targetEnergy, smoothedDiff, newGate)
local sig = {event.pull(0.1, "touch")}
if sig[1] then handleTouch(sig[3], sig[4]) end
prevTime = nowTime
prevEnergy = nowEnergy
end
gpu.setResolution(W, H)
gpu.setBackground(0x000000)
gpu.setForeground(0xFFFFFF)
term.clear()
И нажимаем Ctrl + S (сохранить) и Ctrl + W (закрыть).
ПослеПерезагрузите перезагружаемкомпьютер систему командойкомандой:
reboot
5. Управление программой
После перезапуска у нас сразуперезагрузки откроется программаинтерфейс стабилизациистабилизации. Вы увидите текущее состояние ядра и мынастройки будем видеть его состояниелимитов.

УправлениеРегулировка простоецелевого уровня энергии:
ЛКМ по кнопкам "+" или "-": изменение на 1 млрд (1B).
Ctrl + иЛКМ: -изменение дляна регулирования10 количествамлрд (10B).
Shift + ЛКМ: изменение на 100 млрд (100B).
Логика работы:
Если энергии в ядреЛКМ добавитьменьше илиустановленной отнять 1B (млрд)Ctrl+ЛКМ добавить или отнять 10B (млрд)Shift+ЛКМ добавить или отнять 100B (млрд)
Когда количество энергии дойдет до той что вы выставилицели - лишняяФлаксовый гейт закрыт (энергия начнетне выходитьуходит).
Как Еслитолько цель энергии не достигнута - через гейт энергияоткрывается.
Если уровень энергии продолжает расти выше цели - программа автоматически повышает пропускную способность гейта, пока ситуация не идетЕслистабилизируется.