Гайды
- Дракониевый реактор
- Контроллер ядра энергии
- Ритуал по пробуждению дракониевых блоков
- Ритуал по призыву дракона
- Мультиблочное хранилище RF энергии
- 5 дракониевых реакторов в одном ПК
- Стабилизация Энергетического ядра Draconic Evolution через OpenComputers
Дракониевый реактор
Перед началом
Перед запуском убедитесь, что у вас уже установлено Хранилище.
Необходимые материалы для реактора:
- 1 Драконье ядро реактора
- 4 Стабилизатора реактора
- 1 Реакторный инжектор энергии
- 8 Драконьих блоков
- 2 Флаксовых гейта
- 9 Продвинутых энергетических реле
- Компаратор
Дополнительно для компьютера:
- Преобразователь энергии
- Блок конденсаторов
- 3 Адаптера
- 2 Монитора (ур. 3)
- Клавиатура
- Системный блок (ур. 3)
- Центральный процессор (ур. 3)
- Видеокарта (ур. 3)
- Память (ур. 3.5) – 2 шт.
- Жесткий диск (ур. 3)
- EEPROM (Lua BIOS)
- Дискета с openOS
Выбор правильного места
Для установки реактора и хранилища нужно выбрать один чанк. Это важно, так как если они будут находиться в разных чанках, реактор может взорваться из-за особенностей работы сервера. Чтобы отобразить границы чанков, нажмите F9.
Важно: Ничто не должно выходить за пределы выбранного чанка, даже один блок, иначе это может вызвать проблемы.
Сборка реактора
- Определитесь с размерами реактора. Он может быть разного размера, но стандартный размер — это 11 на 11 блоков (с 4 блоками воздуха между ядром и стабилизаторами).
Пример
- Установите стабилизаторы, ядро и инжектор в правильном порядке:
- Сначала разместите 4 стабилизатора по всем четырём сторонам.
- Затем установите ядро так, чтобы оно "видело" все стабилизаторы (между ними не должно быть никаких препятствий).
- Инжектор размещается на расстоянии в 1 блок от любого стабилизатора.
В итоге должно получиться как на картинке:
Если в стабилизаторе появляется надпись "неправильная структура", проверьте расположение блоков.
Подключение гейтов и компьютера
- Установите флаксовые гейты и подключите их к компьютеру, как показано на изображении:
Примечание: У гейтов есть две точки подключения энергии: синий вход и оранжевый выход. Следите за тем, чтобы подключение было правильным.
- Настройте инжектор. Для этого зажмите
Shiftи трижды нажмите ПКМ по инжектору. В чате появится сообщение "Сдерживание поля [Инвертирован]", а на компораторе загорятся два красных факела.
Настройка трансиверов
1. Разместите и подключите трансиверы, как на изображении:
2. Переключите режимы трансиверов с "выход" на "вход" на оранжевых точках (на выходах гейтов и реактора). Для этого измените режимы связывателя кристаллов, нажав Shift + ПКМ по воздуху до появления нужного режима в чате:
3. Подключаем реактор к хранилищу
Важно: для каждого реактора необходимо ставить отдельный набор трансиверов
Важно: нужно переключить режим трансивера с "выход" на "вход".
Действия на компьютере
-
Устанавливаем операционную систему:
install Y [Enter]Ждем предложения о перезагрузке:
Y [Enter] -
Добавляем пользователей:
useradd <ник>Сначала прописываем себя, потом человека, которому ставим систему.
-
Загружаем скрипт:
pastebin get YmiZmuzQ reactor.lua (В последнее время наблюдаются проблемы с доступом) или wget https://raw.githubusercontent.com/nikita2007558/hiTechClassic/refs/heads/main/reactor.lua -
Запускаем программу:
reactor.lua -
Настройка программы: При первом запуске мы увидим этот экран:
Здесь нужно выбрать адаптеры, к которым подключены гейты. Просто нажмите в любом порядке на адреса гейтов.
Затем проверяем гейты. В левом (подключённом к инжектору) гейте должна быть надпись:
Если это не так, нажмите кнопку "Изменить" и прожмите адреса в другом порядке, затем снова проверяйте гейты. Если всё правильно, прожимаем кнопку "Продолжить".
Запуск реактора
- Откройте стабилизатор и положите в реактор 8 драконьих блоков.
- Откройте компьютер, нажмите кнопку "Зарядить". Теперь ждём, пока реактор зарядится — для этого в хранилище должно быть около 1B энергии.
- Когда реактор зарядится и нагреется до 2000 градусов, появится кнопка "Запустить реактор". Нажмите её.
- Ждите, пока реактор нагреется до 6000-7000 градусов, затем нажмите кнопку "Автономный режим". Температура должна стабилизироваться на уровне около 8000 градусов.
Контроллер ядра энергии
Сборка схемы
Действия на компьютере
install
Y [Enter]
Y [Enter]
useradd <ник>
Сначала прописываем себя, потом человека, которому ставим систему.
pastebin get i7tz8mPu gate.lua (В последнее время наблюдаются проблемы с доступом)
или
wget https://raw.githubusercontent.com/nikita2007558/hiTechClassic/refs/heads/main/gate.lua
.shrc для редактирования:edit .shrc
gate.lua
Ctrl + S и Ctrl + W.1.lua:edit gate.lua
maxCoreEnergy = 1000 * 10^9
Можно указать любое желаемое значение. Где `1000` – это миллиарды (В) в ядре.
Ctrl + S и Ctrl + W.reboot
Ритуал по пробуждению дракониевых блоков
Альтернативно можно крафтить в Дракониевом сборщике 1 уровня.
Для ритуала нам понадобится:
- Заряженный дракониевый блок - 4шт.
- Сердце дракона - 1шт.
- Драконье ядро - 16шт.
- Динамит - 1шт.
- Активатор для динамита (рычаг, красный факел, блок красного камня...) - 1шт.
Ставим 4 Заряженных дракониевых блоков вместе:
Ставим динамит:
Кидаем Сердце дракона рядом с динамитом:
Активируем динамит:
После взрыва динамита сердце активируется: увеличится в размере и начнёт парить.
Будет небольшой промежуток времени за который нужно успеть кинуть к сердцу 16 Дракониевых ядер:
Внимание! Не подходите слишком близко к сердцу, чтобы случайно его не подобрать, кидайте ядра сверху.
Сердце поглотит ядра и начнет очень быстро вращаться, после взрыва появятся Пробужденные дракониевые блоки:
Ритуал по призыву дракона
Призыв дракона — важная часть игры. После его убийства выпадает Сердце дракона, а также на вершине портала в Верхний мир появляется Яйцо дракона. Дополнительно вы получаете опыт и Дракниевую пыль.
Дракона можно убить и обычным оружием, однако важно помнить: во время призыва начинают бить молнии, и они могут попасть по игроку. Спасти от урона и смерти способна только Драконья броня и выше. Также учтите, что у дракона большой запас здоровья, и он регенерирует его от Кристаллов Края. Лучшее решение — уничтожить кристаллы сразу после призыва.
Ритуал проводится только а Энде.
Список предметов для воскрешения:
- Обсидиан - 4шт.
- Светящийся камень - 4шт.
- Камень воскрешения - 1шт.
- Кварцевая КОЛОНА - 12шт.
- Алмазный блок - 4шт.
- Заряженный дракониевый блок - 4шт.
Есть две версии призыва дракона:
Каноничная
Ставим все как на скриншотах и нажимаем ОДИН раз ПКМ по Камню воскрешения.
Начнут бить молнии, осторожно!
Дракон появится не сразу, нужно подождать.
Упрощенная
Ставим все как на скриншотах и нажимаем ОДИН раз ПКМ по Камню воскрешения.
Начнут бить молнии, осторожно!
Дракон появится не сразу, нужно подождать.
Мультиблочное хранилище RF энергии
Ниже этапы сборки всех уровней мультиблочного хранилища.
Для постройки потребуются блоки красного камня, дракониевые блоки, Ядро энергии и 4 Генератора частиц.
После сбора конструкции нажми Шифт+ПКМ по одному из Генераторов частиц и хранилище активируется.
Для ввода/вывода энергии используй Энергетические пилоны.
Уровень 1
Хранит RF энергии - 45,5 млн.
Уровень 2
Хранит RF энергии - 273 млн.
Дракониевый блок - 6 шт.
Уровень 3
Хранит RF энергии - 1.64 млрд.
Дракониевый блок - 26 шт.
Уровень 4
Хранит RF энергии - 9.88 млрд.
Дракониевый блок - 54 шт.
Блок красного камня - 26 шт.
Уровень 5
Хранит RF энергии - 59.3 млрд.
Дракониевый блок - 98 шт.
Блок красного камня - 80 шт.
Уровень 6
Хранит RF энергии - 356 млрд.
Дракониевый блок - 150 шт.
Блок красного камня - 133 шт.
Уровень 7
Хранит RF энергии - 2.14 трлн.
Дракониевый блок - 218 шт.
Блок красного камня - 328 шт.
5 дракониевых реакторов в одном ПК
Этот гайд поможет вам обуздать мощь сразу пяти дракониевых реакторов. Система на базе OpenComputers возьмет на себя все расчеты, предотвращая взрывы и обеспечивая стабильный приток энергии на долгие дни.
1. Список компонентов
Для стабильной работы системы управления пятью реакторами нам понадобится мощный сервер и специфическое оборудование Draconic Evolution.
Контрольный узел (Сервер)
| Компонент | Кол-во | Примечание |
| Серверная стойка | 1 шт | Основа системы |
| Сервер (Уровень 3) | 1 шт | Максимальная мощность |
| Монитор (Уровень 3) | 6 шт | Для сетки 3х2 |
| Клавиатура | 1 шт | Ставится на монитор |
| Видеокарта (Уровень 3) | 1 шт | Вставляется в сервер |
| Процессор (ЦП) (Уровень 3) | 1 шт | Вставляется в сервер |
| Память (Уровень 3.5) | 4 шт | Для работы с 5-ю реакторами |
| Компонентная шина (Ур. 3) | 3 шт | Для подключения всех адаптеров |
| Жесткий диск (4МВ) | 1 шт | Уровень 3 |
| Дисковод для стойки | 1 шт | Для установки ОС |
| EEPROM (Lua BIOS) | 1 шт | Прошивка |
| Преобразователь энергии | 1 шт | Питание сервера |
| Кабель | 6 шт | Соединение компонентов |
| Адаптер | 5 шт | По одному на каждый реактор |
Реакторная установка (на 5 реакторов)
-
Ядро энергии: уже настроенное (см. предыдущий гайд).
-
Энергетический пилон: 2 шт.
-
Флаксовый гейт: 10 шт.
-
Стабилизатор реактора: 20 шт.
-
Реакторный инжектор энергии: 5 шт.
-
Драконье ядро реактора: 5 шт.
-
Криостабилизированная труба: 20 шт.
-
Пробужденный дракониевый блок: 40 шт (топливо).
2. Установка реакторов
Физическая сборка
Первым делом нам нужно ядро энергии с программой стабилизации ядра - гайд тут.
-
Локация: Стройте реакторы прямо над вашим Энергетическим ядром. Важно делать это в пределах того же чанка, чтобы избежать ошибок десинхронизации.
Место под реакторы
Ставим реакторы примерно так (не обязательно ставить все 5 сразу, программа работает одинаково и с одним реактором и с пятью)
Установка реакторов
- Порядок: Устанавливайте компоненты реактора строго по инструкции мода, иначе структура не распознается.
- Топливо: Подойдите к столбу из Стабилизаторов, нажмите ПКМ и вставьте по 8 Пробужденных дракониевых блоков в каждый реактор.
Стабилизаторы
Имеем такую картину
Реакторы с топливом
3. Настройка сервера
Сборка и подключение
-
Установите серверную стойку, мониторы и преобразователь энергии. Проложите кабели к мониторам. Запитайте энергией преобразователь энергии.
Вид спереди
Вид сзади
- Настройка стойки: Нажмите ПКМ по стойке. Вставьте сервер и дисковод. Кликните по желтым точкам на корпусе, чтобы задать направление сторон для подключения кабелей.
- Установка ОС: Вставьте дискету OpenOS в дисковод сервера через Shift + ПКМ.
- Установка компонентов: Откройте интерфейс сервера и вставьте видеокарту, процессор, память и шины.
Программная часть
Включите сервер и выполните следующие шаги:
install
Нажимайте Enter, подтверждая установку. В конце система предложит перезагрузку - снова нажмите Enter.
Безопасность и автозапуск
Добавьте себя в список администраторов (команда чувствительна к регистру):
useradd ник
Это мы делали для того чтобы ПК могли пользоваться только вписанные в него пользователи.
Настройте автозапуск программы при включении ПК:
edit .shrc
и дописываем в самом конце такую строку
reactor.lua
И нажимаем Ctrl + S (сохранить) и Ctrl + W (закрыть).
Создание кода
Создайте файл программы:
edit reactor.lua
Вставьте код. Код очень длинный, вставляйте его частями (по 250 строк) из-за ограничений буфера обмена.
Код
local component = require("component")
local event = require("event")
local serialization = require("serialization")
local filesystem = require("filesystem")
local computer = require("computer")
local unicode = require("unicode")
local term = require("term")
local gpu = component.gpu
-- === АВТОМАТИЧЕСКАЯ НАСТРОЙКА РАЗРЕШЕНИЯ ===
local maxW, maxH = gpu.maxResolution()
gpu.setResolution(maxW, maxH)
local W, H = gpu.getResolution()
--------------------------------------------------------------------------------
-- [КОНФИГУРАЦИЯ]
--------------------------------------------------------------------------------
local CFG = {
filename = "/home/reactors.cfg",
maxReactors = 5,
updateInterval = 1.0,
-- Настройки по умолчанию
defaultTargetTemp = 8000,
targetShield = 25,
startShield = 50.0,
startSat = 50.0,
warmupTemp = 2000,
minFuelPct = 10.0,
initialFlow = 300000,
chargeFlow = 1000000,
maxDrainFlow = 2000000
}
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
}
--------------------------------------------------------------------------------
-- [ПЕРЕМЕННЫЕ]
--------------------------------------------------------------------------------
local reactors = {}
local buttons = {}
local running = true
local wizard = { active = false, step = 1, coreAddr = nil, inAddr = nil, outAddr = nil, candidates = {} }
local needFullRedraw = true
--------------------------------------------------------------------------------
-- [ЛОГИКА]
--------------------------------------------------------------------------------
local function saveConfig()
local data = {}
for _, r in ipairs(reactors) do
table.insert(data, { r=r.proxy.address, i=r.gateIn.address, o=r.gateOut.address, auto=r.auto, t=r.targetTemp })
end
local f = io.open(CFG.filename, "w")
f:write(serialization.serialize(data))
f:close()
end
local function safeCall(func, ...)
local ok, res = pcall(func, ...)
return ok and res or nil
end
local function getFlow(proxy)
if not proxy then return 0 end
return tonumber(safeCall(proxy.getSignalLowFlow)) or 0
end
local function setFlow(proxy, val)
if proxy then safeCall(proxy.setSignalLowFlow, math.floor(val)) end
end
local function tickReactors()
for _, r in ipairs(reactors) do
local info = safeCall(r.proxy.getReactorInfo)
if info then
r.isOnline = true
r.info = info
if not r.targetTemp then r.targetTemp = CFG.defaultTargetTemp end
local status = tostring(info.status or "off"):lower()
local temp = tonumber(info.temperature) or 0
local drain = tonumber(info.fieldDrainRate) or 0
local gen = tonumber(info.generationRate) or 0
local field = tonumber(info.fieldStrength) or 0
local maxField = tonumber(info.maxFieldStrength) or 1
local fuel = tonumber(info.fuelConversion) or 0
local maxFuel = tonumber(info.maxFuelConversion) or 1
local sat = tonumber(info.energySaturation) or 0
local maxSat = tonumber(info.maxEnergySaturation) or 1
r.temp = temp
r.gen = gen
r.drain = drain
r.fieldPct = (maxField > 0) and (field/maxField)*100 or 0
r.fuelPct = (maxFuel > 0) and (1 - (fuel/maxFuel)) * 100 or 0
r.satPct = (maxSat > 0) and (sat/maxSat) * 100 or 0
r.statusStr = status:upper()
r.maxFuel = maxFuel
-- === ЛОГИКА ЗАПУСКА ===
if r.isStarting then
r.auto = false
setFlow(r.gateOut, 0)
if maxFuel == 0 or r.fuelPct <= 0 then
r.modeStr = "НЕТ ТОПЛИВА"
else
if status == "cold" or status == "cooling" or status == "offline" or status == "stopping" then
r.modeStr = "ИНИЦИАЛИЗАЦИЯ"
safeCall(r.proxy.chargeReactor)
elseif status == "charging" then
if r.fieldPct < CFG.startShield then r.modeStr = "ЗАРЯДКА ПОЛЯ"
else r.modeStr = "ЗАРЯДКА НАСЫЩ." end
if r.fieldPct >= CFG.startShield and r.satPct >= CFG.startSat then
safeCall(r.proxy.activateReactor); r.modeStr = "АКТИВАЦИЯ..."
end
elseif status == "charged" then
r.modeStr = "ГОТОВ К ПУСКУ"
safeCall(r.proxy.activateReactor)
elseif status == "warming_up" or status == "warming up" then
r.modeStr = "ПРОГРЕВ > " .. CFG.warmupTemp
if temp >= CFG.warmupTemp then r.isStarting = false; r.auto = true end
elseif status == "running" or status == "online" then
r.isStarting = false; r.auto = true
end
end
end
-- === УПРАВЛЕНИЕ ЩИТОМ ===
if status == "charging" or status == "warming_up" or status == "warming up" then
setFlow(r.gateIn, CFG.chargeFlow); r.shieldCost = CFG.chargeFlow
elseif status ~= "off" and status ~= "cold" then
if r.fieldPct < 15 then setFlow(r.gateIn, CFG.chargeFlow); r.shieldCost = CFG.chargeFlow
else
local targetIn = math.ceil(drain / (1 - (CFG.targetShield / 100)))
local safeIn = math.max(10000, targetIn)
setFlow(r.gateIn, safeIn); r.shieldCost = safeIn
end
else setFlow(r.gateIn, 0); r.shieldCost = 0 end
-- === УПРАВЛЕНИЕ ВЫХОДОМ ===
if (status == "stopping" or status == "cooling") and not r.isStarting then
r.auto = false
r.modeStr = "ОСТЫВАНИЕ"
if r.satPct > 10 then setFlow(r.gateOut, CFG.maxDrainFlow)
else setFlow(r.gateOut, CFG.initialFlow) end
elseif r.auto then
if r.fuelPct <= CFG.minFuelPct and (status == "running" or status == "online") then
safeCall(r.proxy.stopReactor); r.auto = false; r.isStarting = false
r.modeStr = "ТОПЛИВО < 10%"; saveConfig()
elseif status == "running" or status == "online" then
local target = r.targetTemp
local crit = target + 150
if temp > crit then
r.modeStr = "!!! ПЕРЕГРЕВ !!!"
setFlow(r.gateOut, CFG.initialFlow)
elseif temp > target then
local overheat = temp - target
local range = crit - target
local penalty = (overheat / range) * 0.8
local multiplier = 1.0 - penalty
if multiplier < 0.1 then multiplier = 0.1 end
r.modeStr = string.format("УДЕРЖАНИЕ %.0f", temp)
setFlow(r.gateOut, math.max(CFG.initialFlow, gen * multiplier))
else
local underheat = target - temp
local aggressive = 1.0 + (underheat * 0.0005)
if aggressive > 2.0 then aggressive = 2.0 end
r.modeStr = string.format("НАГРЕВ -> %.0f", target)
setFlow(r.gateOut, math.max(CFG.initialFlow, gen * aggressive))
end
else if not r.isStarting then r.modeStr = "ОЖИДАНИЕ" end end
else
if not r.isStarting and status ~= "stopping" and status ~= "cooling" then
if r.fuelPct <= CFG.minFuelPct then r.modeStr = "ТОПЛИВО < MIN"
elseif status == "cold" or status == "offline" then r.modeStr = "СТОП"
else r.modeStr = "РУЧНОЙ" end
if getFlow(r.gateOut) > CFG.initialFlow then setFlow(r.gateOut, CFG.initialFlow) end
end
end
else r.isOnline = false end
end
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 drawVal(x, y, w, str, fg, bg) if bg then gpu.setBackground(bg) end; gpu.fill(x, y, w, 1, " "); if fg then gpu.setForeground(fg) end; gpu.set(x, y, str) end
local function fmt(num) if num > 1000000000 then return string.format("%.2f G", num/1000000000) elseif num > 1000000 then return string.format("%.2f M", num/1000000) elseif num > 1000 then return string.format("%.0f K", num/1000) else return tostring(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 > 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()
local margin = 1; local areaH = math.floor(H * 0.66); local tileW = math.floor(W / 5) - margin; local tileH = areaH - 2
for i = 1, 5 do
local x = 1 + (i-1) * (tileW + margin); local y = 2
rect(x, y, tileW, tileH, COLORS.tileBg); rect(x, y, tileW, 3, COLORS.tileHeader)
center(x, y+1, tileW, "РЕАКТОР #" .. i, COLORS.text, COLORS.tileHeader)
local r = reactors[i]
if r then
local tBg = COLORS.tileBg
text(x+2, y+9, "ТОПЛИВО:", COLORS.label, tBg); text(x+2, y+12, "ЩИТ ПОЛЯ:", COLORS.label, tBg)
text(x+2, y+15, "НАСЫЩЕНИЕ:", COLORS.label, tBg)
local curY = y+18
text(x+2, curY, "ВЫРАБОТКА:", COLORS.label, tBg); text(x+2, curY+1, "ЗАТРАТЫ:", COLORS.label, tBg)
text(x+2, curY+2, "ИТОГ:", COLORS.label, tBg); text(x+2, curY+4, "ВЫХОД:", COLORS.label, tBg)
else center(x, y+10, tileW, "СЛОТ СВОБОДЕН", COLORS.label, COLORS.tileBg) end
end
local areaY = math.floor(H * 0.66) + 2; local areaH = H - areaY + 1
rect(1, areaY, W, areaH, 0x181818); rect(1, areaY, W, 1, 0x444444)
local col2 = 40; local col3 = 80; local line1 = areaY + 2; local line2 = areaY + 4
text(col2, line1, "ОБЩАЯ ГЕНЕРАЦИЯ:", COLORS.label, 0x181818); text(col2, line2, "РАСХОД НА ЩИТЫ:", COLORS.label, 0x181818); text(col3, line1, "ЧИСТАЯ ПРИБЫЛЬ:", COLORS.energy, 0x181818)
local crY = H - 3; local crX = W - 40
text(crX, crY, "Разработчик: DesOope", COLORS.label, 0x181818); text(crX, crY+1, "Проект: McSkill", COLORS.label, 0x181818); text(crX, crY+2, "Сервер: HitechClassic 1.7.10", COLORS.label, 0x181818)
btn("exit", 3, H-2, 10, 1, "ВЫХОД", COLORS.bad)
end
local function updateLiveDisplay()
-- ИСПРАВЛЕНИЕ: Очищаем список кнопок, чтобы удалить фантомные старые кнопки
buttons = {}
-- Сразу возвращаем кнопку выхода, так как мы стерли всё
buttons["exit"] = {x=3, y=H-2, w=10, h=1}
local margin = 1; local areaH = math.floor(H * 0.66); local tileW = math.floor(W / 5) - margin; local tileH = areaH - 2
local totalGen = 0; local totalCost = 0; local totalProfit = 0; local activeCount = 0
for _, r in ipairs(reactors) do
if r and r.isOnline and (r.statusStr == "ONLINE" or r.statusStr == "RUNNING") then
activeCount = activeCount + 1; local p = (r.gen or 0) - (r.shieldCost or 0)
totalGen = totalGen + (r.gen or 0); totalCost = totalCost + (r.shieldCost or 0); totalProfit = totalProfit + p
end
end
for i = 1, 5 do
local x = 1 + (i-1) * (tileW + margin); local y = 2; local r = reactors[i]
if r then
if r.isOnline then
local curProfit = (r.gen or 0) - (r.shieldCost or 0)
local stCol = (r.statusStr == "ONLINE" or r.statusStr == "RUNNING") and COLORS.good or COLORS.warn
if r.statusStr == "OFFLINE" then stCol = COLORS.bad end
if r.statusStr == "COOLING" or r.statusStr == "STOPPING" then stCol = COLORS.energy end
center(x, y+4, tileW, r.statusStr, stCol, COLORS.tileBg)
local modeCol = (r.auto and COLORS.energy or COLORS.warn)
if r.modeStr == "!!! АВАРИЯ !!!" then modeCol = COLORS.bad end
if r.isStarting then modeCol = COLORS.good end
center(x, y+5, tileW, "[" .. (r.modeStr or "-") .. "]", modeCol, COLORS.tileBg)
local tCol = r.temp > (r.targetTemp + 50) and COLORS.warn or COLORS.good
if r.temp > (r.targetTemp + 150) then tCol = COLORS.bad end
local tempStr = string.format("%.0f C", r.temp)
local targetStr = string.format("(Цель: %d)", r.targetTemp or 8000)
center(x, y+7, tileW, tempStr, tCol, COLORS.tileBg)
center(x, y+8, tileW, targetStr, COLORS.label, COLORS.tileBg)
local cx = x + math.floor(tileW/2)
btn("tdn_"..i, cx - 9, y+7, 3, 1, "-", COLORS.btn, COLORS.text)
btn("tup_"..i, cx + 6, y+7, 3, 1, "+", COLORS.btn, COLORS.text)
local fuelCol = r.fuelPct <= CFG.minFuelPct and COLORS.bad or COLORS.fuel
drawVal(x+tileW-6, y+9, 5, string.format("%d%%", r.fuelPct), fuelCol, COLORS.tileBg)
progressBar(x+2, y+10, tileW-4, r.fuelPct, fuelCol, 0x444400)
drawVal(x+tileW-6, y+12, 5, string.format("%d%%", r.fieldPct), COLORS.energy, COLORS.tileBg)
progressBar(x+2, y+13, tileW-4, r.fieldPct, COLORS.energy, 0x002244)
local satCol = r.satPct > 50 and COLORS.warn or COLORS.sat
drawVal(x+tileW-6, y+15, 5, string.format("%d%%", r.satPct), satCol, COLORS.tileBg)
progressBar(x+2, y+16, tileW-4, r.satPct, satCol, 0x332200)
local curY = y+18
drawVal(x+tileW-11, curY, 9, fmt(r.gen), COLORS.good, COLORS.tileBg)
drawVal(x+tileW-11, curY+1, 9, fmt(r.shieldCost), COLORS.warn, COLORS.tileBg)
drawVal(x+tileW-11, curY+2, 9, fmt(curProfit), COLORS.energy, COLORS.tileBg)
drawVal(x+tileW-11, curY+4, 9, fmt(getFlow(r.gateOut)), COLORS.text, COLORS.tileBg)
local by = y + tileH - 4
local btnText, btnColor, btnAct
if r.auto or r.isStarting or (r.statusStr == "RUNNING" or r.statusStr == "ONLINE") then
btnText = "СТОП"; btnColor = COLORS.bad; btnAct = "stop"; if r.isStarting then btnText = "ОТМЕНА" end
else btnText = "ПУСК"; btnColor = COLORS.good; btnAct = "start" end
btn(btnAct.."_"..i, x+2, by, tileW-4, 3, btnText, btnColor)
btn("del_"..i, x+tileW-3, y, 3, 1, "X", COLORS.bad, COLORS.text)
else
center(x, y+10, tileW, "НЕТ СВЯЗИ", COLORS.bad, COLORS.tileBg); center(x, y+11, tileW, "ПРОВЕРЬ КАБЕЛЬ", COLORS.label, COLORS.tileBg)
btn("del_"..i, x+2, y+tileH-2, tileW-4, 1, "УДАЛИТЬ", COLORS.bad)
end
else if i == #reactors + 1 then btn("add", x+4, y+12, tileW-8, 3, "ДОБАВИТЬ", COLORS.good) end end
end
local areaY = math.floor(H * 0.66) + 2; local col1 = 3; local col2 = 40; local col3 = 80; local line1 = areaY + 2; local line2 = areaY + 4; local bgF = 0x181818
gpu.setBackground(bgF); gpu.fill(col1, line1, 30, 1, " "); gpu.set(col1, line1, "АКТИВНО: " .. activeCount .. " / " .. CFG.maxReactors)
drawVal(col2+18, line1, 15, fmt(totalGen).." RF/t", COLORS.good, bgF); drawVal(col2+18, line2, 15, fmt(totalCost).." RF/t", COLORS.warn, bgF); drawVal(col3, line2, 15, fmt(totalProfit).." RF/t", COLORS.energy, bgF)
end
local function drawWizard()
gpu.setBackground(COLORS.bg); term.clear(); local cx = math.floor(W/2); local cy = math.floor(H/2)
center(1, cy-7, W, "=== БЫСТРАЯ НАСТРОЙКА ===", COLORS.energy, COLORS.bg)
if wizard.step == 1 then
center(1, cy-4, W, "Поиск свободного ядра...", COLORS.text, COLORS.bg)
if wizard.coreAddr then
center(1, cy-3, W, "Ядро найдено: " .. wizard.coreAddr:sub(1,8).."...", COLORS.good, COLORS.bg)
center(1, cy-1, W, "ПОИСК ГЕЙТОВ...", COLORS.energy, COLORS.bg)
center(1, cy+1, W, "1. Подойдите к гейту ЩИТА (ВХОД)", COLORS.label, COLORS.bg)
center(1, cy+2, W, "2. Установите на нем поток: 100 RF/t", COLORS.warn, COLORS.bg)
center(1, cy+3, W, "Второй гейт определится АВТОМАТИЧЕСКИ.", COLORS.good, COLORS.bg)
center(1, cy+5, W, "Жду сигнала 100...", COLORS.text, COLORS.bg)
else center(1, cy-2, W, "СВОБОДНОЕ ЯДРО НЕ НАЙДЕНО!", COLORS.bad, COLORS.bg) end
end
btn("cancel_wiz", cx-8, cy+7, 16, 1, "ОТМЕНА", COLORS.bad)
end
local function tickWizard()
if not wizard.active then return end
if not wizard.coreAddr then
for addr, type in component.list("draconic_reactor") do
local used = false; for _, r in ipairs(reactors) do if r.proxy.address == addr then used = true; break end end
if not used then wizard.coreAddr = addr; drawWizard(); break end
end
end
if not wizard.coreAddr then return end
if #wizard.candidates == 0 then
for addr, type in component.list("flux_gate") do
local used = false; for _, r in ipairs(reactors) do if r.gateIn.address == addr or r.gateOut.address == addr then used = true; break end end
if not used then table.insert(wizard.candidates, component.proxy(addr)) end
end
end
for _, gate in ipairs(wizard.candidates) do
local flow = tonumber(gate.getSignalLowFlow()) or 0
if flow == 100 then
wizard.inAddr = gate.address
for _, other in ipairs(wizard.candidates) do if other.address ~= wizard.inAddr then wizard.outAddr = other.address; break end end
if wizard.outAddr then
computer.beep(1000, 0.2)
table.insert(reactors, { proxy = component.proxy(wizard.coreAddr), gateIn = component.proxy(wizard.inAddr), gateOut = component.proxy(wizard.outAddr), auto = false, isStarting = false, isOnline = true, temp=0, gen=0, shieldCost=0, fuelPct=0, fieldPct=0, satPct=0, targetTemp=CFG.defaultTargetTemp })
saveConfig(); wizard.active = false; needFullRedraw = true; tickReactors(); break
end
end
end
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 == "add" then wizard.active = true; wizard.step = 1; wizard.candidates = {}; wizard.coreAddr = nil; drawWizard()
elseif id == "cancel_wiz" then wizard.active = false; needFullRedraw = true
else
local act, idx = id:match("(%a+)_(%d+)"); idx = tonumber(idx); local r = reactors[idx]
if r then
if act == "del" then table.remove(reactors, idx); saveConfig(); needFullRedraw = true
elseif act == "start" then r.isStarting = true; r.auto = false; computer.beep(1000, 0.1); updateLiveDisplay()
elseif act == "stop" then safeCall(r.proxy.stopReactor); r.auto = false; r.isStarting = false; r.modeStr = "СТОП"; saveConfig(); updateLiveDisplay()
elseif act == "tup" then r.targetTemp = (r.targetTemp or 8000) + 50; if r.targetTemp > 20000 then r.targetTemp = 20000 end; saveConfig(); computer.beep(1200,0.05); updateLiveDisplay()
elseif act == "tdn" then r.targetTemp = (r.targetTemp or 8000) - 50; if r.targetTemp < 2000 then r.targetTemp = 2000 end; saveConfig(); computer.beep(1000,0.05); updateLiveDisplay()
end
end
end
computer.beep(800, 0.05); break
end
end
end
gpu.setResolution(maxW, maxH); gpu.setBackground(COLORS.bg); term.clear()
if filesystem.exists(CFG.filename) then
local f = io.open(CFG.filename, "r"); local data = serialization.unserialize(f:read("*a")); f:close()
if data then for _, d in ipairs(data) do table.insert(reactors, { proxy=component.proxy(d.r), gateIn=component.proxy(d.i), gateOut=component.proxy(d.o), auto=d.auto, isOnline=true, isStarting=false, targetTemp=(d.t or CFG.defaultTargetTemp) }) end end
end
needFullRedraw = true
local lastTick = 0
-- === ГЛАВНЫЙ ЦИКЛ ===
while running do
if wizard.active then tickWizard(); local _, _, x, y = event.pull(0.2, "touch"); if x then handleTouch(x, y) end
else
local e, _, x, y = event.pull(0.05, "touch"); if e then handleTouch(x, y) end
if computer.uptime() - lastTick > CFG.updateInterval then tickReactors(); if needFullRedraw then drawStaticInterface(); needFullRedraw = false end; updateLiveDisplay(); lastTick = computer.uptime() end
end
end
gpu.setResolution(maxW, maxH); gpu.setBackground(0x000000); term.clear()
Перезагрузите компьютер командой:
reboot
После перезагрузки мы видим такое окно программы
4. Подключение реакторов к сети
Гейты: Установите флаксовые гейты возле реакторов.
Трубы: Проложите криостабилизированные трубы.
Пилоны: Установите пилоны на трубы. Не забудьте активировать их стеклом снизу. Левый пилон переключите в режим приема энергии (ПКМ по синему ядру).
Трубы: Проложите криостабилизированные трубы с другой стороны.
Важно: С этой стороны трубы нужно разъединить гаечным ключом (например, Yeta из Ender IO), чтобы потоки не смешивались.
Наведитесь между труб и нажмите ПКМ держа в руках гаечный ключ.
|
|
Повторите так со всеми трубами с этой стороны
Инжекторы: Поставьте инжекторы на трубы, направив их в сторону реакторов.
Связь: Установите по очереди (смотреть ниже) по одному Адаптеру между гейтами каждого реактора и соедините их кабелями с сервером.
5. Запуск и эксплуатация
Вернитесь к монитору сервера и следуйте алгоритму:
- Нажмите кнопку "Добавить" в интерфейсе программы.
На экране появится запрос. Подойдите к адаптеру нужного реактора и в его правом гейте вручную выставьте поток 100 RF/t.
Реактор автоматически отобразится в списке.
Повторите эту процедуру с оставшимися реакторами
После того как мы добавили все наши реакторы - жмем пуск и наблюдаем
Что произойдет дальше?
Программа автоматически зарядит щиты, поднимет насыщение, нагреет реакторы, запустит их и они будут работать на стабильных 8000 градусах. В таком режиме система может работать стабильно около 13 реальных дней.
Совет для профи: В программе можно менять рабочую температуру. Если выставить 9000 градусов на 5-10 часов, а потом вернуть на 8000 - топливо выгорит быстрее, что позволит реактору выйти на высокие мощности в 1.5 - 2 млн RF/t. Но делайте это только на свой страх и риск.
Стабилизация Энергетического ядра Draconic Evolution через OpenComputers
Этот гайд поможет вам настроить систему автоматического контроля энергии. Программа следит за тем, чтобы в хранилище всегда оставался необходимый запас для работы реакторов, предотвращая их перегрев или остановку. Если энергии слишком много - компьютер увеличивает выход, если мало - ограничивает его.
1. Необходимые компоненты
Компьютер (OpenComputers)
| Компонент | Количество | Примечание |
| Системный блок | 1 шт | Уровень 3 |
| Монитор | 6 шт | Уровень 3 (для сборки 3х2) |
| Видеокарта | 1 шт | Уровень 3 |
| Процессор (ЦП) | 1 шт | Уровень 3 |
| Память (ОЗУ) | 2 шт | Уровень 3.5 |
| Жесткий диск | 1 шт | Уровень 3 (4 Мб) |
| EEPROM | 1 шт | Прошивка Lua BIOS |
| Дискета | 1 шт | С установщиком OpenOS |
| Адаптер | 1 шт | Для связи с устройствами |
| Преобразователь энергии | 1 шт | Питание компьютера |
| Клавиатура | 1 шт | Для ввода команд |
Ядро энергии
- Само ядро энергии (как его построить)
- Флаксовый гейт - 1шт
- Энергетический пилон - 1шт
- Криостабилизированная флаксовая труба - смотреть по ситуации
2. Подготовка и строительство
Первым делом включите отображение границ чанков (клавиша F9). Крайне важно строить всю конструкцию (ядро и компьютер) в пределах одного чанка, чтобы избежать ошибок при загрузке мира. Инструкция по сборке ядра тут. Схематика тут.
-
Постройте Энергетическое ядро.
Скриншот ядра
-
Установите мониторы (сеткой 3х2) и системный блок. Не забудьте прикрепить клавиатуру к монитору.
Скриншот установки пк и мониторов
Нюансы сборки системного блока
-
Lua BIOS: Обычный чистый EEPROM нужно объединить в сетке крафта с "Руководством OpenComputers".
-
OpenOS: Обычную дискету также соедините с "Руководством OpenComputers", чтобы получить загрузочный диск с операционной системой.
3. Подключение компонентов
Скриншот подключения к ядру
Настройка пилона и гейта
Важное уточнение: стекло на пилон следует ставить с той стороны пилона (верх, низ) которая смотрит в сторону центра ядра энергии. Это для тех, кто собирает схему не четко по инструкции.
-
Энергетический пилон: Установите его и поставьте блок стекла сверху для активации. Нажмите ПКМ по синему ядру внутри пилона, чтобы стрелки были направлены наружу. Это режим отдачи энергии.
-
Флаксовый гейт: Ставьте строго по направлению потока. Фиолетовая сторона (вход) должна смотреть на пилон, оранжевая (выход) - в сторону ваших потребителей.
-
Соединение: Соедините пилон и вход гейта Криостабилизированной трубой (у нее нет лимита передачи).
-
Адаптер: Поставьте адаптер вплотную к Флаксовому гейту, чтобы компьютер мог им управлять.
Важно: Следите, чтобы ядро не переполнялось. Если реакторам некуда будет отдавать энергию, произойдет критический перегрев и взрыв. Выход гейта должен быть подключен к мощному потребителю (например, к Генераторам материи через конвертер).
4. Настройка программной части
Включите компьютер кнопкой в системном блоке.
Сначала мы видим загрузку, после чего у нас появляется вот такое окно
Установка ОС
После загрузки с дискеты введите команду:
install
Нажимайте Enter, подтверждая установку. В конце система предложит перезагрузку - снова нажмите Enter.
Безопасность и автозапуск
Добавьте себя в список администраторов (команда чувствительна к регистру):
useradd ник
Это мы делали для того чтобы ПК могли пользоваться только вписанные в него пользователи.
Настройте автозапуск программы при включении ПК:
edit .shrc
и дописываем в самом конце такую строку
gate.lua
И нажимаем Ctrl + S (сохранить) и Ctrl + W (закрыть).
Создание кода
Создайте файл программы:
edit gate.lua
Вставьте код. Код очень длинный, вставляйте его частями (по 250 строк) из-за ограничений буфера обмена.
Код (v2.0)
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 VERSION = "v 2.0"
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 verX = M + 12 -- Отступ кнопки выхода + пробел
text(verX, footerY, VERSION, COLORS.label, COLORS.bg)
-- Кредиты
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()
-- Мы искусственно отнимаем 1 секунду от времени запуска,
-- чтобы первый кадр отрисовался моментально.
local prevTime = computer.uptime() - 1.0
local prevEnergy = rfStorage.getEnergyStored()
while running do
-- Опрашиваем клики по экрану часто (каждые 0.1 сек), чтобы кнопки работали быстро
local sig = {event.pull(0.1, "touch")}
if sig[1] == "touch" then
handleTouch(sig[3], sig[4])
end
local nowTime = computer.uptime()
local dt = nowTime - prevTime
-- Математика, график и обновление гейта срабатывают ровно 1 раз в секунду
if dt >= 1.0 then
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)
prevTime = nowTime
prevEnergy = nowEnergy
end
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).
Логика работы:
-
Если энергии в ядре меньше установленной цели - Флаксовый гейт закрыт (энергия не уходит).
-
Как только цель достигнута - гейт открывается.
-
Если уровень энергии продолжает расти выше цели - программа автоматически повышает пропускную способность гейта, пока ситуация не стабилизируется.
