From b347855349de38732a5dea3dd796571470e8431a Mon Sep 17 00:00:00 2001 From: Dystroyer8 Date: Thu, 16 Jul 2026 21:44:44 +0200 Subject: [PATCH] Stabilize boiler mapping and clutch fail-safe --- README.md | 16 +++++---- create_boiler_display.lua | 69 ++++++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 490f578..71e8224 100644 --- a/README.md +++ b/README.md @@ -39,13 +39,15 @@ eine Campfire- oder Blaze-Burner-Waermequelle erkannt wird. ### Clutch-Teststeuerung -Die rechte Seite des Computers ist als direkter Redstone-Ausgang fuer eine Test-Clutch -konfiguriert. Der Touch-Button auf dem Advanced Monitor schaltet diesen Ausgang ohne -Invertierung zwischen `CLUTCH SIGNAL: OFF` und `CLUTCH SIGNAL: ON` um. Die Verbindung kann -direkt mit Redstone oder drahtlos ueber ein abgestimmtes Paar Create Redstone Links erfolgen. -Die Boiler-Zuordnung erfolgt nach den internen Peripheral-Namen; die drei Block Reader sollten -deshalb in der Reihenfolge Boiler 1 bis 3 an das Wired Network angeschlossen werden. Jeder Block -Reader muss auf den Controller-Tank des zugeordneten Boiler-Multiblocks zeigen. +Die linke Seite des Computers ist als Redstone-Ausgang fuer die Test-Clutch konfiguriert. +Zwischen Ausgang und Clutch sitzt eine Redstone-Fackel als Fail-safe-Inverter: Ausgang `ON` +bedeutet `PRODUCTION: RUNNING`; Ausgang `OFF`, Programmabbruch oder Computerneustart bedeutet +`PRODUCTION: STOPPED`. Die Verbindung kann direkt oder ueber Create Redstone Links erfolgen. + +Die Boiler werden nicht anhand wechselnder Peripheral-Namen, sondern fest ueber ihre +Controller-Koordinaten `11266/64/10810`, `11260/64/10810` und `11252/64/10810` zugeordnet. +Fehlt ein Reader, bleibt dadurch exakt die betroffene Boiler-Zeile auf `MISSING / NO READER`. +Jeder Block Reader muss direkt auf den Controller-Tank seines Boiler-Multiblocks zeigen. ## Struktur diff --git a/create_boiler_display.lua b/create_boiler_display.lua index 73663b6..e9e5ca4 100644 --- a/create_boiler_display.lua +++ b/create_boiler_display.lua @@ -1,11 +1,16 @@ -- Create boiler status board for CC:Tweaked. -- All Create values are read through Advanced Peripherals Block Readers. -local EXPECTED_BOILERS = 3 local REFRESH_SECONDS = 1 local MIN_WIDTH = 38 local MIN_HEIGHT = 14 -local CLUTCH_OUTPUT_SIDE = "right" +local CLUTCH_OUTPUT_SIDE = "left" + +local BOILERS = { + { label = "BOILER 1", position = { 11266, 64, 10810 } }, + { label = "BOILER 2", position = { 11260, 64, 10810 } }, + { label = "BOILER 3", position = { 11252, 64, 10810 } }, +} local clutchButton = { x1 = 0, x2 = 0, y = 0 } @@ -64,6 +69,13 @@ local function samePosition(a, b) and tonumber(a[3]) == tonumber(b[3]) end +local function positionKey(position) + if type(position) ~= "table" then return nil end + local x, y, z = tonumber(position[1]), tonumber(position[2]), tonumber(position[3]) + if not x or not y or not z then return nil end + return ("%d,%d,%d"):format(x, y, z) +end + local function discoverReaders() local boilers, networks = {}, {} local names = peripheral.getNames() @@ -78,7 +90,9 @@ local function discoverReaders() local speed = getValueIgnoringCase(data, { "Speed" }) if type(boiler) == "table" then - boilers[#boilers + 1] = { name = name, data = data, boiler = boiler } + local position = getValueIgnoringCase(data, { "LastKnownPos", "Controller" }) + local key = positionKey(position) + if key then boilers[key] = { name = name, data = data, boiler = boiler } end elseif type(network) == "table" and tonumber(speed) then networks[#networks + 1] = { name = name, data = data, network = network } end @@ -136,8 +150,10 @@ end local function drawClutchButton(height) local width = monitor.getSize() - local signal = redstone.getOutput(CLUTCH_OUTPUT_SIDE) - local label = signal and " CLUTCH SIGNAL: ON " or " CLUTCH SIGNAL: OFF " + -- With the external redstone-torch inverter, output ON means the clutch is + -- unpowered and production runs. Output OFF is the fail-safe stopped state. + local running = redstone.getOutput(CLUTCH_OUTPUT_SIDE) + local label = running and " PRODUCTION: RUNNING " or " PRODUCTION: STOPPED " local x = math.max(1, math.floor((width - #label) / 2) + 1) local y = math.max(13, height - 1) @@ -149,15 +165,15 @@ local function drawClutchButton(height) monitor.setBackgroundColor(colors.black) monitor.write((" "):rep(width)) monitor.setCursorPos(x, y) - monitor.setBackgroundColor(signal and colors.orange or colors.gray) + monitor.setBackgroundColor(running and colors.lime or colors.red) monitor.setTextColor(colors.black) monitor.write(label) monitor.setBackgroundColor(colors.black) end -local function toggleClutchSignal() - local signal = redstone.getOutput(CLUTCH_OUTPUT_SIDE) - redstone.setOutput(CLUTCH_OUTPUT_SIDE, not signal) +local function toggleProduction() + local running = redstone.getOutput(CLUTCH_OUTPUT_SIDE) + redstone.setOutput(CLUTCH_OUTPUT_SIDE, not running) end local function render() @@ -169,9 +185,10 @@ local function render() monitor.clear() center(1, "CREATE KRAFTWERK", colors.cyan) - for index = 1, EXPECTED_BOILERS do - local state, heatMode, color = readBoiler(boilers[index]) - center(2 + index, ("BOILER %d %-7s %s"):format(index, state, heatMode), color) + for index, configuredBoiler in ipairs(BOILERS) do + local reader = boilers[positionKey(configuredBoiler.position)] + local state, heatMode, color = readBoiler(reader) + center(2 + index, ("%s %-7s %s"):format(configuredBoiler.label, state, heatMode), color) end center(7, "MAIN SHAFT", colors.cyan) @@ -187,7 +204,7 @@ local function render() end drawClutchButton(height) - center(height, "Touch = Redstone umschalten", colors.gray) + center(height, "Touch = Produktion umschalten", colors.gray) monitor.setTextColor(colors.white) monitor.setBackgroundColor(colors.black) term.setCursorPos(1, 1) @@ -206,16 +223,24 @@ end safeRender() local refreshTimer = os.startTimer(REFRESH_SECONDS) -while true do - local event, first, second, third = os.pullEvent() - if event == "timer" and first == refreshTimer then - safeRender() - refreshTimer = os.startTimer(REFRESH_SECONDS) - elseif event == "monitor_touch" then - local x, y = second, third - if y == clutchButton.y and x >= clutchButton.x1 and x <= clutchButton.x2 then - toggleClutchSignal() +local function run() + while true do + local event, first, second, third = os.pullEventRaw() + if event == "terminate" then + return + elseif event == "timer" and first == refreshTimer then safeRender() + refreshTimer = os.startTimer(REFRESH_SECONDS) + elseif event == "monitor_touch" then + local x, y = second, third + if y == clutchButton.y and x >= clutchButton.x1 and x <= clutchButton.x2 then + toggleProduction() + safeRender() + end end end end + +local ok, reason = pcall(run) +redstone.setOutput(CLUTCH_OUTPUT_SIDE, false) +if not ok then error(reason, 0) end