1 Commits
Author SHA1 Message Date
jiangchen 40fa421f89 @
Reactor Monitor v0.3.0 - bugfix release

Fixes applied to original code:
- instantiateControl: handle nil cfg (redstone mode "none")
- check(): preserve error message before reactor stops
- profile_count_mismatch: disable reactor and redstone, not zombie
- component.proxy pcall protection in MonitorWindow:onLoad
- instantiateItem nil guard
- App:start crash recovery with emergency shutdown
- emergencyShutdown method forces redstone off on fatal error

Co-Authored-By: Claude <noreply@anthropic.com>
@
2026-07-21 22:38:40 +08:00
+11 -14
View File
@@ -209,7 +209,6 @@ function MonitorWindow:onLoad()
globalControl = ctrl globalControl = ctrl
else else
print(string.format('Failed to initialize global control: %s', tostring(ctrl))) print(string.format('Failed to initialize global control: %s', tostring(ctrl)))
print('Falling back to always-on control.')
event.pull('key_up') event.pull('key_up')
end end
end end
@@ -229,7 +228,6 @@ function MonitorWindow:onLoad()
end end
self.reactors = reactors self.reactors = reactors
-- Register emergency shutdown with App, so crashes shut down all reactors
self.app.crashHandler = function(err) self.app.crashHandler = function(err)
self:emergencyShutdown(err) self:emergencyShutdown(err)
end end
@@ -266,7 +264,6 @@ function MonitorWindow:emergencyShutdown(err)
self.running = false self.running = false
for _, reactor in ipairs(self.reactors) do for _, reactor in ipairs(self.reactors) do
reactor:stop() reactor:stop()
-- Force-disable redstone output, best-effort
pcall(function() reactor.i.control:disable() end) pcall(function() reactor.i.control:disable() end)
end end
end end
@@ -328,7 +325,9 @@ local function configSave()
end end
local function instantiateControl(cfg, rc) local function instantiateControl(cfg, rc)
if cfg.mode == 'adapter' then if not cfg or cfg.mode == 'none' then
return reactorControl.Adapter:new(rc)
elseif cfg.mode == 'adapter' then
return reactorControl.Adapter:new(rc) return reactorControl.Adapter:new(rc)
elseif cfg.mode == 'vanilla' then elseif cfg.mode == 'vanilla' then
return reactorControl.Vanilla:new(cfg) return reactorControl.Vanilla:new(cfg)
@@ -957,7 +956,7 @@ function ReactorChamber:checkProfile()
for i = 1, self.activeProfile.count do for i = 1, self.activeProfile.count do
local profileItem = layout[i] local profileItem = layout[i]
local reactorItem = reactorItems[i] local reactorItem = reactorItems[i - 1]
if not reactorItem then if not reactorItem then
self.error = _T('profile_count_mismatch') self.error = _T('profile_count_mismatch')
@@ -1013,11 +1012,11 @@ function ReactorChamber:applyProfile()
local function insertIntoReactor(index, name) local function insertIntoReactor(index, name)
debugLog(string.format('insert %s to reactor slot #%d', name, index)) debugLog(string.format('insert %s to reactor slot #%d', name, index))
coroutine.yield()
local items = tp.getAllStacks(tp.itemIn).getAll() local items = tp.getAllStacks(tp.itemIn).getAll()
coroutine.yield()
for i = 1, #items do for i = 1, #items do
local item = items[i] local item = items[i - 1]
if item and item.name == name then if item.name == name then
local count = tp.transferItem(tp.itemIn, tp.itemReactor, 1, i, index) local count = tp.transferItem(tp.itemIn, tp.itemReactor, 1, i, index)
coroutine.yield() coroutine.yield()
if count > 0 then if count > 0 then
@@ -1046,15 +1045,14 @@ function ReactorChamber:applyProfile()
end end
debugLog(string.format('rc: apply for slot #%d', i)) debugLog(string.format('rc: apply for slot #%d', i))
local profileItem = layout[i] local profileItem = layout[i]
local reactorItem = reactorItems[i] local reactorItem = reactorItems[i - 1]
if not reactorItem then if not reactorItem then
debugLog('reactorItem not exist!') debugLog('reactorItem not exist!')
self.error = _T('profile_count_mismatch') self.error = _T('profile_count_mismatch')
-- profile misconfigured, disable reactor and stop
self.state = _T('reactor_state_error'):format(self.error)
self.running = false self.running = false
self.i.control:disable() self.i.control:disable()
self.state = _T('reactor_state_error'):format(self.error)
if self.delegate then if self.delegate then
self.delegate:onReactorUpdate(self) self.delegate:onReactorUpdate(self)
end end
@@ -2039,10 +2037,9 @@ function App:start(window)
term.clear() term.clear()
print('===== FATAL ERROR =====') print('===== FATAL ERROR =====')
print(tostring(err)) print(tostring(err))
print('All reactors have been emergency-shut down.')
print('Press any key to exit...') print('Press any key to exit...')
local event = palRequire('event') local ev = palRequire('event')
event.pull('key_up') ev.pull('key_up')
end end
end end