davedumas0

buildcraft refinery control system for opencomputers

Dec 1st, 2025 (edited)
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 43.05 KB | None | 0 0
  1. ----------------------------------------------------------------
  2. -- Colors
  3. ----------------------------------------------------------------
  4. local colors = {
  5.   white        = 0xFFFFFF,
  6.   black        = 0x000000,
  7.   gray         = 0x808080,
  8.   lightGray    = 0xC0C0C0,
  9.   darkGray     = 0x404040,
  10.  
  11.   red          = 0xFF0000,
  12.   darkRed      = 0x800000,
  13.   orange       = 0xFFA500,
  14.   yellow       = 0xFFFF00,
  15.   gold         = 0xFFD700,
  16.  
  17.   green        = 0x00FF00,
  18.   darkGreen    = 0x006400,
  19.   lime         = 0x32CD32,
  20.   teal         = 0x008080,
  21.   cyan         = 0x00FFFF,
  22.  
  23.   blue         = 0x0000FF,
  24.   lightBlue    = 0xADD8E6,
  25.   darkBlue     = 0x00008B,
  26.   navy         = 0x001F3F,
  27.   purple       = 0x800080,
  28.  
  29.   pink         = 0xFFC0CB,
  30.   magenta      = 0xFF00FF,
  31.   violet       = 0x8A2BE2,
  32.   brown        = 0x8B4513,
  33.   tan          = 0xD2B48C,
  34.  
  35.   -- UI theme
  36.   surface      = 0x11161C,
  37.   surfaceHi    = 0x171E26,
  38.   borderDim    = 0x1C2530,
  39.   borderHi     = 0x243142,
  40.   text         = 0xE6EEF7,
  41.   textDim      = 0x8AA0B5,
  42.   accent       = 0x3DA3FF,
  43.   accentAlt    = 0x56E39F,
  44.   danger       = 0xFF5C5C,
  45.   barEmpty     = 0x1B222B,
  46.   btnOn        = 0x1F3D2A,
  47.   btnOff       = 0x20252B,
  48.  
  49.   ----------------------------------------------------------------
  50.   -- Additions
  51.   ----------------------------------------------------------------
  52.   silver       = 0xC0C0C0, -- alias of lightGray for convenience
  53.   charcoal     = 0x36454F,
  54.   slate        = 0x708090,
  55.   olive        = 0x808000,
  56.   forestGreen  = 0x228B22,
  57.   indigo       = 0x4B0082,
  58.   lavender     = 0xE6E6FA,
  59.   turquoise    = 0x40E0D0,
  60.   coral        = 0xFF7F50,
  61.   amber        = 0xFFBF00,
  62.   royalBlue    = 0x4169E1,
  63.   hotPink      = 0xFF69B4,
  64.  
  65.   ----------------------------------------------------------------
  66.   -- Neon (high-saturation, pop on dark backgrounds)
  67.   ----------------------------------------------------------------
  68.   neonPink     = 0xFF6EC7,
  69.   neonGreen    = 0x39FF14,
  70.   neonBlue     = 0x1F51FF,
  71.   neonPurple   = 0xB026FF,
  72.   neonOrange   = 0xFF5F1F,
  73.   neonYellow   = 0xE9FF00,
  74.   neonCyan     = 0x18FFFF,
  75.   neonRed      = 0xFF073A
  76. }
  77.  
  78. ----------------------------------------------------------------
  79. -- Requires
  80. ----------------------------------------------------------------
  81. local component = require("component")
  82. local button    = require("button")
  83. local progBar   = require("progressBar")  -- kept for compatibility if other code uses it
  84. local panel     = require("panel")
  85. local tankBar   = require("tankBar")
  86. local term      = require("term")
  87. local event     = require("event")
  88. local Line      = require("line")
  89.  
  90. local gpu       = component.gpu
  91. local redstone  = component.redstone
  92.  
  93. ----------------------------------------------------------------
  94. -- Hardware addresses (edit to your setup)
  95. ----------------------------------------------------------------
  96. local gpuAddresses = {
  97.   primary   = "956e2810-a2cd-42e4-9df3-8926be4b5a12",
  98.   secondary = "f9429421-7ac6-4fd0-8e68-a45c64dc2f9a"
  99. }
  100. local screenAddresses = {
  101.   primary   = "46a0b52b-3166-4f2f-b6cc-73432b0ed4b6",
  102.   secondary = "d817695c-bd51-4912-ba82-5928c57775c6"
  103. }
  104.  
  105. ----------------------------------------------------------------
  106. -- State
  107. ----------------------------------------------------------------
  108. local tasks = {}
  109. local fluidMovingInPipe = false
  110.  
  111. ----------------------------------------------------------------
  112. -- Bind two screens/GPUs: returns gpu2 proxy bound to secondary
  113. ----------------------------------------------------------------
  114. local function BindScreens()
  115.   component.setPrimary("gpu", gpuAddresses.primary)
  116.   gpu.bind(screenAddresses.primary)
  117.   local gpu2 = component.proxy(gpuAddresses.secondary)
  118.   gpu2.bind(screenAddresses.secondary)
  119.   return gpu2
  120. end
  121. local gpu2 = BindScreens()
  122.  
  123. ----------------------------------------------------------------
  124. -- Tanks & addresses
  125. ----------------------------------------------------------------
  126. local tanks = {
  127.   bank_01 = {
  128.     tank_01 = "94cee3b7-45f2-4f02-bd96-abe62b6a8b78",
  129.     tank_02 = "88cf1273-1546-4cbf-9182-48e3a5ba79af",
  130.     tank_03 = "2c4cdc29-ee56-4c4a-981a-72ec3bb469d1",
  131.     tank_04 = "e5ce0c81-ceec-4224-8726-4821801f1245",
  132.     tank_05 = "3dd07ec3-2666-4b78-812a-3d5e1653c432",
  133.     tank_06 = "55776a61-951e-4ecc-8cd0-5ed95f91cbd1",
  134.     tank_07 = "2a1d111c-ea8b-498a-90ca-180b9c2017e0",
  135.     tank_08 = "5fc36d02-13a4-4aad-af2f-3a5bdf0df5d3",
  136.     tank_09 = "6836a513-285b-46ce-a865-bafc6d82291a"
  137.   },
  138.   bank_02 = {
  139.     tank_01 = "3c2d05db-97a7-4612-99dd-91cad1742443",
  140.     tank_02 = "5335f1b2-14ce-4646-bffb-6d9963c1423c",
  141.     tank_03 = "480a3682-cab9-4e68-8ec6-c6de1fc2f149",
  142.     tank_04 = "bc9a16bf-05e9-4b4a-9b40-fcd9c07b21f8",
  143.     tank_05 = "f028ba55-0d0d-494a-9bc2-d49ea39c97d9",
  144.     tank_06 = "a62abe76-2afd-4b31-b040-41562ca9f948",
  145.     tank_07 = "d530bcc2-7440-4d7d-9450-c034dc944e84",
  146.     tank_08 = "62215813-4b69-4d4a-9221-79483975f72b",
  147.     tank_09 = "ffee74d1-c3be-46bf-a50d-567678dc815f"
  148.   }
  149. }
  150.  
  151. -- heat exchanger buffer tanks addresses
  152. local heatExchangerCoolInputBufferTankAdress  = "f323adb7-e821-42ac-8cff-56cdf1d2cdda"
  153. local heatExchangerHotInputBufferTankAdress   = "f1f957b1-d6bf-4df8-ac9c-0182ec1d5962"
  154. local heatExchangerCoolOutputBufferTankAdress = "a6baca15-4841-4811-bbe4-11388a5b5305"
  155. local heatExchangerHotOutputBufferTankAdress  = "3a5b7c59-0e5b-47fd-8fd1-65e6484500e1"
  156.  
  157. -- note distiller tank pumps into heat exchanger output buffer tanks for sorting
  158. local distillerOutputTankTop    = "694c9e60-56c7-4156-9c7e-f6559008821f"
  159. local distillerOutputTankBottom = "753c2514-1b77-46b4-9560-fd3bf532c177"
  160.  
  161. -- mass storage for cool oil (crude oil from ground)
  162. local crudeOilTank = component.pp_tank
  163.  
  164. ----------------------------------------------------------------
  165. -- Redstone: bundled cable sides & channels
  166. ----------------------------------------------------------------
  167. -- sides
  168. local storageTankPumpsBank_01_Side        = 1 -- top
  169. local storageTankinputBank_02_Side        = 3 -- back
  170.  
  171. -- channels
  172. -- heat exchanger input and refinery valves
  173. local heatExchangerInputChanel_cool = 0 -- white/north valve
  174. local heatExchangerInputChanel_hot  = 1 -- orange/top
  175.  
  176. local refineryOutputBottomTankPump_channel = 5 -- HeatExchangerAndRefineryInputSide
  177. local refineryOutputTopTankPump_channel    = 4 -- HeatExchangerAndRefineryInputSide
  178.  
  179. local fluidInTransit = false
  180.  
  181. local tankPumpMapping = {
  182.   bank_01 = {
  183.     tank_01 = { address = tanks.bank_01.tank_01, side = storageTankPumpsBank_01_Side, channel = 0 },
  184.     tank_02 = { address = tanks.bank_01.tank_02, side = storageTankPumpsBank_01_Side, channel = 1 },
  185.     tank_03 = { address = tanks.bank_01.tank_03, side = storageTankPumpsBank_01_Side, channel = 2 },
  186.     tank_04 = { address = tanks.bank_01.tank_04, side = storageTankPumpsBank_01_Side, channel = 3 },
  187.     tank_05 = { address = tanks.bank_01.tank_05, side = storageTankPumpsBank_01_Side, channel = 4 },
  188.     tank_06 = { address = tanks.bank_01.tank_06, side = storageTankPumpsBank_01_Side, channel = 5 },
  189.     tank_07 = { address = tanks.bank_01.tank_07, side = storageTankPumpsBank_01_Side, channel = 6 },
  190.     tank_08 = { address = tanks.bank_01.tank_08, side = storageTankPumpsBank_01_Side, channel = 7 },
  191.     tank_09 = { address = tanks.bank_01.tank_09, side = storageTankPumpsBank_01_Side, channel = 8 },
  192.   },
  193.   bank_02 = {
  194.     tank_01 = { address = tanks.bank_02.tank_01, side = storageTankinputBank_02_Side, channel = 0 },
  195.     tank_02 = { address = tanks.bank_02.tank_02, side = storageTankinputBank_02_Side, channel = 1 },
  196.     tank_03 = { address = tanks.bank_02.tank_03, side = storageTankinputBank_02_Side, channel = 2 },
  197.     tank_04 = { address = tanks.bank_02.tank_04, side = storageTankinputBank_02_Side, channel = 3 },
  198.     tank_05 = { address = tanks.bank_02.tank_05, side = storageTankinputBank_02_Side, channel = 4 },
  199.     tank_06 = { address = tanks.bank_02.tank_06, side = storageTankinputBank_02_Side, channel = 5 },
  200.     tank_07 = { address = tanks.bank_02.tank_07, side = storageTankinputBank_02_Side, channel = 6 },
  201.     tank_08 = { address = tanks.bank_02.tank_08, side = storageTankinputBank_02_Side, channel = 7 },
  202.     tank_09 = { address = tanks.bank_02.tank_09, side = storageTankinputBank_02_Side, channel = 8 },
  203.   }
  204. }
  205.  
  206. local routMapping = {
  207.   bank_01 = {
  208.     tank_01 = { address = tanks.bank_01.tank_01, side = 4, channel = 0 },
  209.     tank_02 = { address = tanks.bank_01.tank_02, side = 4, channel = 1 },
  210.     tank_03 = { address = tanks.bank_01.tank_03, side = 4, channel = 2 },
  211.     tank_04 = { address = tanks.bank_01.tank_04, side = 4, channel = 3 },
  212.     tank_05 = { address = tanks.bank_01.tank_05, side = 4, channel = 4 },
  213.     tank_06 = { address = tanks.bank_01.tank_06, side = 4, channel = 5 },
  214.     tank_07 = { address = tanks.bank_01.tank_07, side = 4, channel = 6 },
  215.     tank_08 = { address = tanks.bank_01.tank_08, side = 4, channel = 7 },
  216.     tank_09 = { address = tanks.bank_01.tank_09, side = 4, channel = 8 },
  217.   },
  218.   bank_02 = {
  219.     tank_01 = { address = tanks.bank_02.tank_01, side = 2, channel = 0 },
  220.     tank_02 = { address = tanks.bank_02.tank_02, side = 2, channel = 1 },
  221.     tank_03 = { address = tanks.bank_02.tank_03, side = 2, channel = 2 },
  222.     tank_04 = { address = tanks.bank_02.tank_04, side = 2, channel = 3 },
  223.     tank_05 = { address = tanks.bank_02.tank_05, side = 2, channel = 4 },
  224.     tank_06 = { address = tanks.bank_02.tank_06, side = 2, channel = 5 },
  225.     tank_07 = { address = tanks.bank_02.tank_07, side = 2, channel = 6 },
  226.     tank_08 = { address = tanks.bank_02.tank_08, side = 2, channel = 7 },
  227.     tank_09 = { address = tanks.bank_02.tank_09, side = 2, channel = 8 },
  228.   },
  229.   fluidProccessing = {
  230.     hx= {hotInput = {address = heatExchangerHotInputBufferTankAdress, side = 5, channel = heatExchangerInputChanel_hot},
  231.          coldInput = {address = heatExchangerCoolInputBufferTankAdress, side = 5, channel = heatExchangerInputChanel_cool}},
  232.     distiller = {input = {address = nil, side = 5, channel = heatExchangerInputChanel_hot}}
  233.   }
  234. }
  235.  
  236. local valves = {
  237.    routingValveProccessingInput = {
  238.      state = "",
  239.      stateControls = {openNorth = 0, openTop = 2, openEast = 3}
  240.    },
  241. }
  242.  
  243. ----------------------------------------------------------------
  244. -- UI registries
  245. ----------------------------------------------------------------
  246. local primaryScreenChildren   = {}
  247. local secondaryScreenChildren = {}
  248. local heatableFluidsAvailable = {}
  249. local coolableFluidsAvailable = {}
  250.  
  251. ----------------------------------------------------------------
  252. -- Tabs (framework) — TANKS (left side of secondary screen)
  253. ----------------------------------------------------------------
  254. local tabs = {}                 -- { {name="…"}, … }
  255. local tabButtons = {}           -- buttons across the top
  256. local currentTab = 1
  257. local TabContent = {}           -- [tabIndex] = { child1, child2, ... }
  258.  
  259. -- area that a tab "owns" on the secondary screen
  260. local tabHost = { x = 3, y = 7, w = 50, h = 40, gpu = nil }
  261.  
  262. local function clear_tab_host()
  263.   local g = tabHost.gpu or gpu2
  264.   g.setBackground(colors.surface or 0x11161C)
  265.   g.fill(tabHost.x, tabHost.y, tabHost.w, tabHost.h, " ")
  266. end
  267.  
  268. local function draw_tab_underline(idx, on)
  269.   local btn = tabButtons[idx]
  270.   if not btn then return end
  271.   local g = btn.gpu or gpu2
  272.   local ux = btn.x
  273.   local uy = btn.y + btn.h
  274.   local uw = btn.w
  275.   g.setBackground(on and (colors.accent or 0x3DA3FF) or (colors.borderDim or 0x1C2530))
  276.   g.fill(ux, uy, uw, 1, " ")
  277. end
  278.  
  279. local function draw_tabbar()
  280.   for i = 1, #tabButtons do
  281.     tabButtons[i]:draw()
  282.     draw_tab_underline(i, i == currentTab)
  283.   end
  284. end
  285.  
  286. local function draw_tabcontent()
  287.   clear_tab_host()
  288.   local list = TabContent[currentTab]
  289.   if not list then return end
  290.   for i = 1, #list do
  291.     if list[i].draw then list[i]:draw() end
  292.   end
  293. end
  294.  
  295. local function select_tab(i)
  296.   if i < 1 or i > #tabs or i == currentTab then return end
  297.   currentTab = i
  298.   draw_tabbar()
  299.   draw_tabcontent()
  300. end
  301.  
  302. -- API: add a new tab button + storage for its children
  303. function AddNewTab(name, color)
  304.   local idx = #tabs + 1
  305.   tabs[idx] = { name = name, color = color }
  306.   TabContent[idx] = {}
  307.  
  308.   local x = 2 + (idx - 1) * 10      -- 9 wide + 1 gap
  309.   local y = 2
  310.   local btn = button:new(x, y, 9, 5, name, function() select_tab(idx) end)
  311.   btn.gpu = gpu2
  312.   btn.behavior = "momentary"
  313.   table.insert(tabButtons, btn)
  314.   table.insert(secondaryScreenChildren, btn)
  315.   return idx
  316. end
  317.  
  318. -- API: add any drawable element to a tab (it will be drawn only when active)
  319. function AddToTab(tabIndex, el)
  320.   TabContent[tabIndex] = TabContent[tabIndex] or {}
  321.   table.insert(TabContent[tabIndex], el)
  322. end
  323.  
  324. ----------------------------------------------------------------
  325. -- Button Panel Tabs (right-side panel on secondary screen)
  326. ----------------------------------------------------------------
  327. local btnTabs = {}                 -- { {name="…"}, … }
  328. local btnTabButtons = {}           -- buttons within the right panel header
  329. local btnCurrentTab = 1
  330. local ButtonTabContent = {}        -- [tabIndex] = { el1, el2, ... }
  331.  
  332. -- host area inside the right panel (panel at 55,7 size 100x40)
  333. local btnTabHost = { x = 57, y = 12, w = 96, h = 33, gpu = nil }
  334.  
  335. local function clear_btn_tab_host()
  336.   local g = btnTabHost.gpu or gpu2
  337.   g.setBackground(colors.surface or 0x11161C)
  338.   g.fill(btnTabHost.x, btnTabHost.y, btnTabHost.w, btnTabHost.h, " ")
  339. end
  340.  
  341. local function draw_btn_tab_underline(idx, on)
  342.   local btn = btnTabButtons[idx]
  343.   if not btn then return end
  344.   local g = btn.gpu or gpu2
  345.   local ux = btn.x
  346.   local uy = btn.y + btn.h
  347.   local uw = btn.w
  348.   g.setBackground(on and (colors.accent or 0x3DA3FF) or (colors.borderDim or 0x1C2530))
  349.   g.fill(ux, uy, uw, 1, " ")
  350. end
  351.  
  352. local function draw_buttonpanel_tabbar()
  353.   for i = 1, #btnTabButtons do
  354.     btnTabButtons[i]:draw()
  355.     draw_btn_tab_underline(i, i == btnCurrentTab)
  356.   end
  357. end
  358.  
  359. local function draw_buttonpanel_tabcontent()
  360.   clear_btn_tab_host()
  361.   local list = ButtonTabContent[btnCurrentTab]
  362.   if not list then return end
  363.   for i = 1, #list do
  364.     if list[i].draw then list[i]:draw() end
  365.   end
  366. end
  367.  
  368. local function select_buttonpanel_tab(i)
  369.   if i < 1 or i > #btnTabs or i == btnCurrentTab then return end
  370.   btnCurrentTab = i
  371.   draw_buttonpanel_tabbar()
  372.   draw_buttonpanel_tabcontent()
  373. end
  374.  
  375. -- API: add a new tab to the button panel
  376. function AddNewButtonPanelTab(name, color)
  377.   local idx = #btnTabs + 1
  378.   btnTabs[idx] = { name = name, color = color }
  379.   ButtonTabContent[idx] = {}
  380.  
  381.   -- tab bar across top of the panel (start at x=57, y=8), 9 wide + 1 gap
  382.   local x = 57 + (idx - 1) * 10
  383.   local y = 8
  384.   local tabBtn = button:new(x, y, 9, 3, name, function() select_buttonpanel_tab(idx) end)
  385.   tabBtn.gpu = gpu2
  386.   tabBtn.behavior = "momentary"
  387.   table.insert(btnTabButtons, tabBtn)
  388.   table.insert(secondaryScreenChildren, tabBtn) -- so clicks are handled
  389.   return idx
  390. end
  391.  
  392. -- API: add any element to a button-panel tab
  393. function AddToButtonPanelTab(tabIndex, el)
  394.   ButtonTabContent[tabIndex] = ButtonTabContent[tabIndex] or {}
  395.   table.insert(ButtonTabContent[tabIndex], el)
  396. end
  397.  
  398. ----------------------------------------------------------------
  399. -- (Optional) Heat Exchanger schematic placeholder
  400. ----------------------------------------------------------------
  401. function CreateHeatEx_Image(x, y)
  402.   local line_01 = Line:new(x, y+2, x+20, y+2, colors.silver, 1, " ")
  403.   local line_02 = Line:new(x+20, y+1, x+20, y-2, colors.silver, 1, " ")
  404.   line_01.gpu = gpu
  405.   line_02.gpu = gpu
  406.   local line_03 = Line:new(x-2, y+2, x-2, y-2, colors.silver, 1, " ")
  407.   local line_04 = Line:new(x-1, y-2, x+18, y-2, colors.silver, 1, " ")
  408.   local line_05 = Line:new(x-3, y+1, x+21, y+1, colors.cyan, 1, " ")
  409.   local line_06 = Line:new(x-3, y-1, x+21, y-1, colors.cyan, 1, " ")
  410.   line_06.gpu = gpu
  411.   line_05.gpu = gpu
  412.   line_03.gpu = gpu
  413.   line_04.gpu = gpu
  414.   table.insert(primaryScreenChildren, line_06)
  415.   table.insert(primaryScreenChildren, line_05)
  416.   table.insert(primaryScreenChildren, line_01)
  417.   table.insert(primaryScreenChildren, line_02)
  418.   table.insert(primaryScreenChildren, line_03)
  419.   table.insert(primaryScreenChildren, line_04)
  420. end
  421.  
  422. function CreateDistiller_Image(x, y)
  423.   local line_01 = Line:new(x, y, x+8, y, colors.darkRed, 5, " ")
  424.   line_01.gpu = gpu
  425.   table.insert(primaryScreenChildren, line_01)
  426. end
  427.  
  428. function CreateStorageOutput_image(x, y)
  429.   local stor = {}
  430.   stor.line_01 = Line:new(x, y, x+11, y, colors.charcoal, 30, " ")
  431.   stor.line_01.gpu = gpu
  432.   stor.pumpActive = "none"
  433.   table.insert(primaryScreenChildren, stor.line_01)
  434.   return stor
  435. end
  436.  
  437. function CreateStorageInput_image(x, y)
  438.   local stor = {}
  439.   stor.line_01 = Line:new(x, y, x+11, y, colors.charcoal, 30, " ")
  440.   stor.line_01.gpu = gpu
  441.   stor.pumpActive = "none"
  442.   table.insert(primaryScreenChildren, stor.line_01)
  443.   return stor
  444. end
  445.  
  446. function CreatePipes()
  447.   local pipes = {
  448.     pipe_01 = {
  449.       lines = {
  450.         line_01 = Line:new(22, 15, 57, 15, colors.brown, 1, " ")
  451.       },
  452.       inuse = false
  453.     },
  454.  
  455.     pipe_02 = {
  456.       lines = {
  457.         line_01 = Line:new(22, 22, 59, 22, colors.brown, 1, " "),
  458.         line_02 = Line:new(59, 22, 59, 17, colors.brown, 1, " ")
  459.       },
  460.       inuse = false
  461.     },
  462.  
  463.     pipe_03 = {
  464.       lines = {
  465.         line_01 = Line:new(79, 13, 79, 7, colors.brown, 1, " "),
  466.         line_02 = Line:new(79, 7, 129, 7, colors.brown, 1, " ")
  467.       },
  468.       inuse = false
  469.     },
  470.  
  471.     pipe_04 = {
  472.       lines = {
  473.         line_01 = Line:new(79, 13, 79, 7, colors.brown, 1, " ")
  474.       },
  475.       inuse = false
  476.     },
  477.  
  478.     pipe_05 = {
  479.       lines = {
  480.         line_01 = Line:new(81, 15, 129, 15, colors.brown, 1, " ")
  481.       },
  482.       inuse = false
  483.     },
  484.  
  485.     pipe_06 = {
  486.       lines = {
  487.         line_01 = Line:new(22, 33, 69, 33, colors.brown, 1, " ")
  488.       },
  489.       inuse = false
  490.     },
  491.  
  492.     pipe_07 = {
  493.       lines = {
  494.         line_01 = Line:new(76, 30, 129, 30, colors.brown, 1, " ")
  495.       },
  496.       inuse = false
  497.     },
  498.  
  499.     pipe_08 = {
  500.       lines = {
  501.         line_01 = Line:new(76, 36, 133, 36, colors.brown, 1, " ")
  502.       },
  503.       inuse = false
  504.     },
  505.   }
  506.  
  507.   -- hook all pipe lines to gpu + primaryScreenChildren
  508.   for _, pipe in pairs(pipes) do
  509.     for _, line in pairs(pipe.lines) do
  510.       line.gpu = gpu
  511.       table.insert(primaryScreenChildren, line)
  512.     end
  513.   end
  514.  
  515.   return pipes
  516. end
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526. function ToggleDistillerValve()
  527.   if redstone.getBundledInput(5, 9) > 0 then
  528.     redstone.setBundledOutput(5, 9, 0)
  529.   else
  530.     redstone.setBundledOutput(5, 9, 255)
  531.   end
  532. end
  533.  
  534.  
  535.  
  536.  
  537. function FindTankWithFluid(fluid, tempState)
  538.   for _, bank in pairs(tanks) do
  539.     for _, tankAddr in pairs(bank) do
  540.       local tankProxy = component.proxy(tankAddr)
  541.       if tankProxy then
  542.         local contents = tankProxy.getFluidInTank(1)
  543.         if contents and contents[1] then
  544.           local f = contents[1]
  545.           local hasFluid = f.name and f.name == fluid
  546.           local hasTemp = not tempState or (f.label and f.label:lower():find(tempState:lower()))
  547.           if hasFluid and hasTemp then
  548.             return tankAddr
  549.           end
  550.         end
  551.       end
  552.     end
  553.   end
  554.   return nil -- no match found
  555. end
  556.  
  557. function EnableCoolSideHxBufferPump()
  558.   -- Prevent overlapping transfers
  559.   TogglePump(5, 6)
  560. end
  561.  
  562. function EnableHotSideHxBufferPump()
  563.   TogglePump(5, 8)
  564. end
  565.  
  566.  
  567.  
  568. ----------------------------------------------------------------
  569. -- Screens: layout & widgets
  570. ----------------------------------------------------------------
  571. function LoadScreens()
  572.   -- main containers on secondary screen
  573.  
  574.   -- right-side control stack panel (background only)
  575.   local _buttonPanel = panel:new(55, 7, 100, 40)
  576.   _buttonPanel.gpu = gpu2
  577.   table.insert(secondaryScreenChildren, _buttonPanel)
  578.  
  579.   -- TANK tabs host (left)
  580.   tabHost.x, tabHost.y, tabHost.w, tabHost.h = 2, 7, 42, 40
  581.   tabHost.gpu = gpu2
  582.  
  583.   -- BUTTON-PANEL tabs host (right, inside the panel)
  584.   btnTabHost.x, btnTabHost.y, btnTabHost.w, btnTabHost.h = 57, 12, 96, 33
  585.   btnTabHost.gpu = gpu2
  586.  
  587.   -- create BUTTON-PANEL tabs
  588.   local bt1 = AddNewButtonPanelTab("Valves")
  589.   local bt2 = AddNewButtonPanelTab("Pumps")
  590.   local bt3 = AddNewButtonPanelTab("Config")
  591.  
  592.   -- controls for Valves tab (positioned inside btnTabHost)
  593.   local hx = btnTabHost.x + 2
  594.   local hy = btnTabHost.y + 2
  595.  
  596. function ToggleHXHotValve()
  597.   if redstone.getBundledInput(5, 1) > 0 then
  598.     redstone.setBundledOutput(5, 1, 0)
  599.   else
  600.     redstone.setBundledOutput(5, 1, 255)
  601.   end
  602. end
  603.  
  604.   local btnTHHV = button:new(hx, hy, 30, 3, "toggle HX Hot valve", ToggleHXHotValve)
  605.   btnTHHV.gpu = gpu2
  606.   AddToButtonPanelTab(bt1, btnTHHV)
  607.  
  608. function ToggleHXCoolValve()
  609.   if redstone.getBundledInput(5, 0) > 0 then
  610.     redstone.setBundledOutput(5, 0, 0)
  611.   else
  612.     redstone.setBundledOutput(5, 0, 255)
  613.   end
  614. end
  615.  
  616.   local btnTHCV = button:new(hx, hy + 4, 30, 3, "toggle HX Cool valve", ToggleHXCoolValve)
  617.   btnTHCV.gpu = gpu2
  618.   AddToButtonPanelTab(bt1, btnTHCV)
  619.  
  620. function ToggleDistillerValve()
  621.   if redstone.getBundledInput(5, 9) > 0 then
  622.     redstone.setBundledOutput(5, 9, 0)
  623.   else
  624.     redstone.setBundledOutput(5, 9, 255)
  625.   end
  626. end
  627.  
  628.   local btnTDV = button:new(hx, hy + 8, 30, 3, "toggle Distiller valve", ToggleDistillerValve)
  629.   btnTDV.gpu = gpu2
  630.   AddToButtonPanelTab(bt1, btnTDV)
  631.  
  632.  
  633.  
  634. ----------------------------------------------------------------
  635.   -- BANK 1 valves
  636.   --------------------------------------------------------------
  637.  
  638. function ToggleB1T1Valve()
  639.   if redstone.getBundledInput(routMapping.bank_01.tank_01.side, routMapping.bank_01.tank_01.channel) > 0 then
  640.     redstone.setBundledOutput(routMapping.bank_01.tank_01.side, routMapping.bank_01.tank_01.channel, 0)
  641.   else
  642.     redstone.setBundledOutput(routMapping.bank_01.tank_01.side, routMapping.bank_01.tank_01.channel, 255)
  643.   end
  644. end
  645.  
  646.   local btnTB1T1 = button:new(hx+31, hy, 30, 3, "toggle bank-tank 01 valve", ToggleB1T1Valve)
  647.   btnTB1T1.gpu = gpu2
  648.   AddToButtonPanelTab(bt1, btnTB1T1)
  649.  
  650.   function ToggleB1T2Valve()
  651.     if redstone.getBundledInput(routMapping.bank_01.tank_02.side, routMapping.bank_01.tank_02.channel) > 0 then
  652.       redstone.setBundledOutput(routMapping.bank_01.tank_02.side, routMapping.bank_01.tank_02.channel, 0)
  653.     else
  654.       redstone.setBundledOutput(routMapping.bank_01.tank_02.side, routMapping.bank_01.tank_02.channel, 255)
  655.     end
  656.   end
  657.   local btnTB1T2 = button:new(hx+31, hy+3, 30, 3, "toggle bank-tank 02 valve", ToggleB1T2Valve)
  658.   btnTB1T2.gpu = gpu2
  659.   AddToButtonPanelTab(bt1, btnTB1T2)
  660.  
  661.   function ToggleB1T3Valve()
  662.     if redstone.getBundledInput(routMapping.bank_01.tank_03.side, routMapping.bank_01.tank_03.channel) > 0 then
  663.       redstone.setBundledOutput(routMapping.bank_01.tank_03.side, routMapping.bank_01.tank_03.channel, 0)
  664.     else
  665.       redstone.setBundledOutput(routMapping.bank_01.tank_03.side, routMapping.bank_01.tank_03.channel, 255)
  666.     end
  667.   end
  668.   local btnTB1T3 = button:new(hx+31, hy+3*2, 30, 3, "toggle bank-tank 03 valve", ToggleB1T3Valve)
  669.   btnTB1T3.gpu = gpu2
  670.   AddToButtonPanelTab(bt1, btnTB1T3)
  671.  
  672.   function ToggleB1T4Valve()
  673.     if redstone.getBundledInput(routMapping.bank_01.tank_04.side, routMapping.bank_01.tank_04.channel) > 0 then
  674.       redstone.setBundledOutput(routMapping.bank_01.tank_04.side, routMapping.bank_01.tank_04.channel, 0)
  675.     else
  676.       redstone.setBundledOutput(routMapping.bank_01.tank_04.side, routMapping.bank_01.tank_04.channel, 255)
  677.     end
  678.   end
  679.   local btnTB1T4 = button:new(hx+31, hy+3*3, 30, 3, "toggle bank-tank 04 valve", ToggleB1T4Valve)
  680.   btnTB1T4.gpu = gpu2
  681.   AddToButtonPanelTab(bt1, btnTB1T4)
  682.  
  683.   function ToggleB1T5Valve()
  684.     if redstone.getBundledInput(routMapping.bank_01.tank_05.side, routMapping.bank_01.tank_05.channel) > 0 then
  685.       redstone.setBundledOutput(routMapping.bank_01.tank_05.side, routMapping.bank_01.tank_05.channel, 0)
  686.     else
  687.       redstone.setBundledOutput(routMapping.bank_01.tank_05.side, routMapping.bank_01.tank_05.channel, 255)
  688.     end
  689.   end
  690.   local btnTB1T5 = button:new(hx+31, hy+3*4, 30, 3, "toggle bank-tank 05 valve", ToggleB1T5Valve)
  691.   btnTB1T5.gpu = gpu2
  692.   AddToButtonPanelTab(bt1, btnTB1T5)
  693.  
  694.   function ToggleB1T6Valve()
  695.     if redstone.getBundledInput(routMapping.bank_01.tank_06.side, routMapping.bank_01.tank_06.channel) > 0 then
  696.       redstone.setBundledOutput(routMapping.bank_01.tank_06.side, routMapping.bank_01.tank_06.channel, 0)
  697.     else
  698.       redstone.setBundledOutput(routMapping.bank_01.tank_06.side, routMapping.bank_01.tank_06.channel, 255)
  699.     end
  700.   end
  701.   local btnTB1T6 = button:new(hx+31, hy+3*5, 30, 3, "toggle bank-tank 06 valve", ToggleB1T6Valve)
  702.   btnTB1T6.gpu = gpu2
  703.   AddToButtonPanelTab(bt1, btnTB1T6)
  704.  
  705.   function ToggleB1T7Valve()
  706.     if redstone.getBundledInput(routMapping.bank_01.tank_07.side, routMapping.bank_01.tank_07.channel) > 0 then
  707.       redstone.setBundledOutput(routMapping.bank_01.tank_07.side, routMapping.bank_01.tank_07.channel, 0)
  708.     else
  709.       redstone.setBundledOutput(routMapping.bank_01.tank_07.side, routMapping.bank_01.tank_07.channel, 255)
  710.     end
  711.   end
  712.   local btnTB1T7 = button:new(hx+31, hy+3*6, 30, 3, "toggle bank-tank 07 valve", ToggleB1T7Valve)
  713.   btnTB1T7.gpu = gpu2
  714.   AddToButtonPanelTab(bt1, btnTB1T7)
  715.  
  716.   function ToggleB1T8Valve()
  717.     if redstone.getBundledInput(routMapping.bank_01.tank_08.side, routMapping.bank_01.tank_08.channel) > 0 then
  718.       redstone.setBundledOutput(routMapping.bank_01.tank_08.side, routMapping.bank_01.tank_08.channel, 0)
  719.     else
  720.       redstone.setBundledOutput(routMapping.bank_01.tank_08.side, routMapping.bank_01.tank_08.channel, 255)
  721.     end
  722.   end
  723.   local btnTB1T8 = button:new(hx+31, hy+3*7, 30, 3, "toggle bank-tank 08 valve", ToggleB1T8Valve)
  724.   btnTB1T8.gpu = gpu2
  725.   AddToButtonPanelTab(bt1, btnTB1T8)
  726.  
  727.   function ToggleB1T9Valve()
  728.     if redstone.getBundledInput(routMapping.bank_01.tank_09.side, routMapping.bank_01.tank_09.channel) > 0 then
  729.       redstone.setBundledOutput(routMapping.bank_01.tank_09.side, routMapping.bank_01.tank_09.channel, 0)
  730.     else
  731.       redstone.setBundledOutput(routMapping.bank_01.tank_09.side, routMapping.bank_01.tank_09.channel, 255)
  732.     end
  733.   end
  734.   local btnTB1T9 = button:new(hx+31, hy+3*8, 30, 3, "toggle bank-tank 09 valve", ToggleB1T9Valve)
  735.   btnTB1T9.gpu = gpu2
  736.   AddToButtonPanelTab(bt1, btnTB1T9)
  737.  
  738.   ----------------------------------------------------------------
  739.   -- BANK 2 valves
  740.   ----------------------------------------------------------------
  741.   function ToggleB2T1Valve()
  742.     if redstone.getBundledInput(routMapping.bank_02.tank_01.side, routMapping.bank_02.tank_01.channel) > 0 then
  743.       redstone.setBundledOutput(routMapping.bank_02.tank_01.side, routMapping.bank_02.tank_01.channel, 0)
  744.     else
  745.       redstone.setBundledOutput(routMapping.bank_02.tank_01.side, routMapping.bank_02.tank_01.channel, 255)
  746.     end
  747.   end
  748.   local btnTB2T1 = button:new(hx+62, hy, 30, 3, "toggle bank2-tank 01 valve", ToggleB2T1Valve)
  749.   btnTB2T1.gpu = gpu2
  750.   AddToButtonPanelTab(bt1, btnTB2T1)
  751.  
  752.   function ToggleB2T2Valve()
  753.     if redstone.getBundledInput(routMapping.bank_02.tank_02.side, routMapping.bank_02.tank_02.channel) > 0 then
  754.       redstone.setBundledOutput(routMapping.bank_02.tank_02.side, routMapping.bank_02.tank_02.channel, 0)
  755.     else
  756.       redstone.setBundledOutput(routMapping.bank_02.tank_02.side, routMapping.bank_02.tank_02.channel, 255)
  757.     end
  758.   end
  759.   local btnTB2T2 = button:new(hx+62, hy+3*1, 30, 3, "toggle bank2-tank 02 valve", ToggleB2T2Valve)
  760.   btnTB2T2.gpu = gpu2
  761.   AddToButtonPanelTab(bt1, btnTB2T2)
  762.  
  763.   function ToggleB2T3Valve()
  764.     if redstone.getBundledInput(routMapping.bank_02.tank_03.side, routMapping.bank_02.tank_03.channel) > 0 then
  765.       redstone.setBundledOutput(routMapping.bank_02.tank_03.side, routMapping.bank_02.tank_03.channel, 0)
  766.     else
  767.       redstone.setBundledOutput(routMapping.bank_02.tank_03.side, routMapping.bank_02.tank_03.channel, 255)
  768.     end
  769.   end
  770.   local btnTB2T3 = button:new(hx+62, hy+3*2, 30, 3, "toggle bank2-tank 03 valve", ToggleB2T3Valve)
  771.   btnTB2T3.gpu = gpu2
  772.   AddToButtonPanelTab(bt1, btnTB2T3)
  773.  
  774.   function ToggleB2T4Valve()
  775.     if redstone.getBundledInput(routMapping.bank_02.tank_04.side, routMapping.bank_02.tank_04.channel) > 0 then
  776.       redstone.setBundledOutput(routMapping.bank_02.tank_04.side, routMapping.bank_02.tank_04.channel, 0)
  777.     else
  778.       redstone.setBundledOutput(routMapping.bank_02.tank_04.side, routMapping.bank_02.tank_04.channel, 255)
  779.     end
  780.   end
  781.   local btnTB2T4 = button:new(hx+62, hy+3*3, 30, 3, "toggle bank2-tank 04 valve", ToggleB2T4Valve)
  782.   btnTB2T4.gpu = gpu2
  783.   AddToButtonPanelTab(bt1, btnTB2T4)
  784.  
  785.   function ToggleB2T5Valve()
  786.     if redstone.getBundledInput(routMapping.bank_02.tank_05.side, routMapping.bank_02.tank_05.channel) > 0 then
  787.       redstone.setBundledOutput(routMapping.bank_02.tank_05.side, routMapping.bank_02.tank_05.channel, 0)
  788.     else
  789.       redstone.setBundledOutput(routMapping.bank_02.tank_05.side, routMapping.bank_02.tank_05.channel, 255)
  790.     end
  791.   end
  792.   local btnTB2T5 = button:new(hx+62, hy+3*4, 30, 3, "toggle bank2-tank 05 valve", ToggleB2T5Valve)
  793.   btnTB2T5.gpu = gpu2
  794.   AddToButtonPanelTab(bt1, btnTB2T5)
  795.  
  796.   function ToggleB2T6Valve()
  797.     if redstone.getBundledInput(routMapping.bank_02.tank_06.side, routMapping.bank_02.tank_06.channel) > 0 then
  798.       redstone.setBundledOutput(routMapping.bank_02.tank_06.side, routMapping.bank_02.tank_06.channel, 0)
  799.     else
  800.       redstone.setBundledOutput(routMapping.bank_02.tank_06.side, routMapping.bank_02.tank_06.channel, 255)
  801.     end
  802.   end
  803.   local btnTB2T6 = button:new(hx+62, hy+3*5, 30, 3, "toggle bank2-tank 06 valve", ToggleB2T6Valve)
  804.   btnTB2T6.gpu = gpu2
  805.   AddToButtonPanelTab(bt1, btnTB2T6)
  806.  
  807.   function ToggleB2T7Valve()
  808.     if redstone.getBundledInput(routMapping.bank_02.tank_07.side, routMapping.bank_02.tank_07.channel) > 0 then
  809.       redstone.setBundledOutput(routMapping.bank_02.tank_07.side, routMapping.bank_02.tank_07.channel, 0)
  810.     else
  811.       redstone.setBundledOutput(routMapping.bank_02.tank_07.side, routMapping.bank_02.tank_07.channel, 255)
  812.     end
  813.   end
  814.   local btnTB2T7 = button:new(hx+62, hy+3*6, 30, 3, "toggle bank2-tank 07 valve", ToggleB2T7Valve)
  815.   btnTB2T7.gpu = gpu2
  816.   AddToButtonPanelTab(bt1, btnTB2T7)
  817.  
  818.   function ToggleB2T8Valve()
  819.     if redstone.getBundledInput(routMapping.bank_02.tank_08.side, routMapping.bank_02.tank_08.channel) > 0 then
  820.       redstone.setBundledOutput(routMapping.bank_02.tank_08.side, routMapping.bank_02.tank_08.channel, 0)
  821.     else
  822.       redstone.setBundledOutput(routMapping.bank_02.tank_08.side, routMapping.bank_02.tank_08.channel, 255)
  823.     end
  824.   end
  825.   local btnTB2T8 = button:new(hx+62, hy+3*7, 30, 3, "toggle bank2-tank 08 valve", ToggleB2T8Valve)
  826.   btnTB2T8.gpu = gpu2
  827.   AddToButtonPanelTab(bt1, btnTB2T8)
  828.  
  829.   function ToggleB2T9Valve()
  830.     if redstone.getBundledInput(routMapping.bank_02.tank_09.side, routMapping.bank_02.tank_09.channel) > 0 then
  831.       redstone.setBundledOutput(routMapping.bank_02.tank_09.side, routMapping.bank_02.tank_09.channel, 0)
  832.     else
  833.       redstone.setBundledOutput(routMapping.bank_02.tank_09.side, routMapping.bank_02.tank_09.channel, 255)
  834.     end
  835.   end
  836.   local btnTB2T9 = button:new(hx+62, hy+3*8, 30, 3, "toggle bank2-tank 09 valve", ToggleB2T9Valve)
  837.   btnTB2T9.gpu = gpu2
  838.   AddToButtonPanelTab(bt1, btnTB2T9)
  839. --------------------------------------------------------
  840. ---
  841. --------------------------------------------------------
  842. ---
  843.   ----------------------------------------------------------------
  844.   -- PUMPS tab controls (BANK 1 + BANK 2)
  845.   ----------------------------------------------------------------
  846.   -- reuse the same base coords pattern as valves
  847.   local px = btnTabHost.x + 2
  848.   local py = btnTabHost.y + 2
  849.  
  850.   --------------------------------------------------------------
  851.   -- BANK 1 pumps
  852.   --------------------------------------------------------------
  853.   function ToggleB1T1Pump()
  854.     local m = tankPumpMapping.bank_01.tank_01
  855.     TogglePump(m.side, m.channel)
  856.   end
  857.  
  858.   local btnPB1T1 = button:new(px, py, 30, 3, "toggle B1 tank 01 pump", ToggleB1T1Pump)
  859.   btnPB1T1.gpu = gpu2
  860.   AddToButtonPanelTab(bt2, btnPB1T1)
  861.  
  862.   function ToggleB1T2Pump()
  863.     local m = tankPumpMapping.bank_01.tank_02
  864.     TogglePump(m.side, m.channel)
  865.   end
  866.   local btnPB1T2 = button:new(px, py+3*1, 30, 3, "toggle B1 tank 02 pump", ToggleB1T2Pump)
  867.   btnPB1T2.gpu = gpu2
  868.   AddToButtonPanelTab(bt2, btnPB1T2)
  869.  
  870.   function ToggleB1T3Pump()
  871.     local m = tankPumpMapping.bank_01.tank_03
  872.     TogglePump(m.side, m.channel)
  873.   end
  874.   local btnPB1T3 = button:new(px, py+3*2, 30, 3, "toggle B1 tank 03 pump", ToggleB1T3Pump)
  875.   btnPB1T3.gpu = gpu2
  876.   AddToButtonPanelTab(bt2, btnPB1T3)
  877.  
  878.   function ToggleB1T4Pump()
  879.     local m = tankPumpMapping.bank_01.tank_04
  880.     TogglePump(m.side, m.channel)
  881.   end
  882.   local btnPB1T4 = button:new(px, py+3*3, 30, 3, "toggle B1 tank 04 pump", ToggleB1T4Pump)
  883.   btnPB1T4.gpu = gpu2
  884.   AddToButtonPanelTab(bt2, btnPB1T4)
  885.  
  886.   function ToggleB1T5Pump()
  887.     local m = tankPumpMapping.bank_01.tank_05
  888.     TogglePump(m.side, m.channel)
  889.   end
  890.   local btnPB1T5 = button:new(px, py+3*4, 30, 3, "toggle B1 tank 05 pump", ToggleB1T5Pump)
  891.   btnPB1T5.gpu = gpu2
  892.   AddToButtonPanelTab(bt2, btnPB1T5)
  893.  
  894.   function ToggleB1T6Pump()
  895.     local m = tankPumpMapping.bank_01.tank_06
  896.     TogglePump(m.side, m.channel)
  897.   end
  898.   local btnPB1T6 = button:new(px, py+3*5, 30, 3, "toggle B1 tank 06 pump", ToggleB1T6Pump)
  899.   btnPB1T6.gpu = gpu2
  900.   AddToButtonPanelTab(bt2, btnPB1T6)
  901.  
  902.   function ToggleB1T7Pump()
  903.     local m = tankPumpMapping.bank_01.tank_07
  904.     TogglePump(m.side, m.channel)
  905.   end
  906.   local btnPB1T7 = button:new(px, py+3*6, 30, 3, "toggle B1 tank 07 pump", ToggleB1T7Pump)
  907.   btnPB1T7.gpu = gpu2
  908.   AddToButtonPanelTab(bt2, btnPB1T7)
  909.  
  910.   function ToggleB1T8Pump()
  911.     local m = tankPumpMapping.bank_01.tank_08
  912.     TogglePump(m.side, m.channel)
  913.   end
  914.   local btnPB1T8 = button:new(px, py+3*7, 30, 3, "toggle B1 tank 08 pump", ToggleB1T8Pump)
  915.   btnPB1T8.gpu = gpu2
  916.   AddToButtonPanelTab(bt2, btnPB1T8)
  917.  
  918.   function ToggleB1T9Pump()
  919.     local m = tankPumpMapping.bank_01.tank_09
  920.     TogglePump(m.side, m.channel)
  921.   end
  922.   local btnPB1T9 = button:new(px, py+3*8, 30, 3, "toggle B1 tank 09 pump", ToggleB1T9Pump)
  923.   btnPB1T9.gpu = gpu2
  924.   AddToButtonPanelTab(bt2, btnPB1T9)
  925.  
  926.   --------------------------------------------------------------
  927.   -- BANK 2 pumps
  928.   --------------------------------------------------------------
  929.   function ToggleB2T1Pump()
  930.     local m = tankPumpMapping.bank_02.tank_01
  931.     TogglePump(m.side, m.channel)
  932.   end
  933.   local btnPB2T1 = button:new(px+31, py, 30, 3, "toggle B2 tank 01 pump", ToggleB2T1Pump)
  934.   btnPB2T1.gpu = gpu2
  935.   AddToButtonPanelTab(bt2, btnPB2T1)
  936.  
  937.   function ToggleB2T2Pump()
  938.     local m = tankPumpMapping.bank_02.tank_02
  939.     TogglePump(m.side, m.channel)
  940.   end
  941.   local btnPB2T2 = button:new(px+31, py+3*1, 30, 3, "toggle B2 tank 02 pump", ToggleB2T2Pump)
  942.   btnPB2T2.gpu = gpu2
  943.   AddToButtonPanelTab(bt2, btnPB2T2)
  944.  
  945.   function ToggleB2T3Pump()
  946.     local m = tankPumpMapping.bank_02.tank_03
  947.     TogglePump(m.side, m.channel)
  948.   end
  949.   local btnPB2T3 = button:new(px+31, py+3*2, 30, 3, "toggle B2 tank 03 pump", ToggleB2T3Pump)
  950.   btnPB2T3.gpu = gpu2
  951.   AddToButtonPanelTab(bt2, btnPB2T3)
  952.  
  953.   function ToggleB2T4Pump()
  954.     local m = tankPumpMapping.bank_02.tank_04
  955.     TogglePump(m.side, m.channel)
  956.   end
  957.   local btnPB2T4 = button:new(px+31, py+3*3, 30, 3, "toggle B2 tank 04 pump", ToggleB2T4Pump)
  958.   btnPB2T4.gpu = gpu2
  959.   AddToButtonPanelTab(bt2, btnPB2T4)
  960.  
  961.   function ToggleB2T5Pump()
  962.     local m = tankPumpMapping.bank_02.tank_05
  963.     TogglePump(m.side, m.channel)
  964.   end
  965.   local btnPB2T5 = button:new(px+31, py+3*4, 30, 3, "toggle B2 tank 05 pump", ToggleB2T5Pump)
  966.   btnPB2T5.gpu = gpu2
  967.   AddToButtonPanelTab(bt2, btnPB2T5)
  968.  
  969.   function ToggleB2T6Pump()
  970.     local m = tankPumpMapping.bank_02.tank_06
  971.     TogglePump(m.side, m.channel)
  972.   end
  973.   local btnPB2T6 = button:new(px+31, py+3*5, 30, 3, "toggle B2 tank 06 pump", ToggleB2T6Pump)
  974.   btnPB2T6.gpu = gpu2
  975.   AddToButtonPanelTab(bt2, btnPB2T6)
  976.  
  977.   function ToggleB2T7Pump()
  978.     local m = tankPumpMapping.bank_02.tank_07
  979.     TogglePump(m.side, m.channel)
  980.   end
  981.   local btnPB2T7 = button:new(px+31, py+3*6, 30, 3, "toggle B2 tank 07 pump", ToggleB2T7Pump)
  982.   btnPB2T7.gpu = gpu2
  983.   AddToButtonPanelTab(bt2, btnPB2T7)
  984.  
  985.   function ToggleB2T8Pump()
  986.     local m = tankPumpMapping.bank_02.tank_08
  987.     TogglePump(m.side, m.channel)
  988.   end
  989.   local btnPB2T8 = button:new(px+31, py+3*7, 30, 3, "toggle B2 tank 08 pump", ToggleB2T8Pump)
  990.   btnPB2T8.gpu = gpu2
  991.   AddToButtonPanelTab(bt2, btnPB2T8)
  992.  
  993.   function ToggleB2T9Pump()
  994.     local m = tankPumpMapping.bank_02.tank_09
  995.     TogglePump(m.side, m.channel)
  996.   end
  997.   local btnPB2T9 = button:new(px+31, py+3*8, 30, 3, "toggle B2 tank 09 pump", ToggleB2T9Pump)
  998.   btnPB2T9.gpu = gpu2
  999.   AddToButtonPanelTab(bt2, btnPB2T9)
  1000.  
  1001. --------------------------------------------------------------
  1002.   -- HX buffer pumps
  1003.   --------------------------------------------------------------
  1004.   function StartHXCoolBufferPump()
  1005.     EnableCoolSideHxBufferPump()
  1006.   end
  1007.   local btnPHXC = button:new(px+62, py, 30, 3, "toggle HX cool pump", StartHXCoolBufferPump)
  1008.   btnPHXC.gpu = gpu2
  1009.   AddToButtonPanelTab(bt2, btnPHXC)
  1010.  
  1011.   function StartHXHotBufferPump()
  1012.     EnableHotSideHxBufferPump()
  1013.   end
  1014.   local btnPHXH = button:new(px+62, py+3*1, 30, 3, "toggle HX hot pump", StartHXHotBufferPump)
  1015.   btnPHXH.gpu = gpu2
  1016.   AddToButtonPanelTab(bt2, btnPHXH)
  1017.  
  1018.   -- remember: the tab buttons themselves were inserted into secondaryScreenChildren by AddNewButtonPanelTab()
  1019.  
  1020.   -- draw schematics (primary screen)
  1021.   CreateHeatEx_Image(60, 15)
  1022.   CreateDistiller_Image(70, 33)
  1023.   CreateStorageOutput_image(10, 20)
  1024.   CreateStorageInput_image(130, 20)
  1025.   CreatePipes()
  1026.  
  1027.  
  1028.   -- create LEFT tabs (tanks)
  1029.   local t1 = AddNewTab("Bank 1")
  1030.   local t2 = AddNewTab("Bank 2")
  1031.   local t3 = AddNewTab("HX")   -- placeholder for heat exchanger view
  1032.  
  1033.   -- initial active tabs
  1034.   currentTab    = 1
  1035.   btnCurrentTab = 1
  1036. end
  1037.  
  1038. function DrawScreens()
  1039.   if primaryScreenChildren then
  1040.     for i = 1, #primaryScreenChildren do
  1041.       if primaryScreenChildren[i].draw then
  1042.         primaryScreenChildren[i]:draw()
  1043.       end
  1044.     end
  1045.   end
  1046.   if secondaryScreenChildren then
  1047.     for i = 1, #secondaryScreenChildren do
  1048.       if secondaryScreenChildren[i].draw then
  1049.         secondaryScreenChildren[i]:draw()
  1050.       end
  1051.     end
  1052.   end
  1053. end
  1054.  
  1055. function UpdateScreens()
  1056.   -- put periodic screen updates here if needed
  1057.   DrawScreens()
  1058. end
  1059.  
  1060. ----------------------------------------------------------------
  1061. -- Helpers
  1062. ----------------------------------------------------------------
  1063. function GetFluidLevelInTank(addr)
  1064.   local t = component.proxy(addr)
  1065.   local tt = t.getTankLevel(1)
  1066.   return tt
  1067. end
  1068.  
  1069. function OpenValve(side, channel)      redstone.setBundledOutput(side, channel, 255) end
  1070. function CloseValve(side, channel)     redstone.setBundledOutput(side, channel, 0)   end
  1071.  
  1072. function TogglePump(side, channel)
  1073.   if redstone.getBundledInput(side, channel) > 0 then
  1074.     redstone.setBundledOutput(side, channel, 0)
  1075.   else
  1076.     redstone.setBundledOutput(side, channel, 255)
  1077.   end
  1078.  
  1079.  
  1080. end
  1081.  
  1082.  
  1083. function CreateTask()
  1084.   -- stub
  1085. end
  1086.  
  1087. function TestFunc()
  1088.   gpu.set(1, 1, tostring(GetFluidLevelInTank(tanks.bank_01.tank_01)))
  1089. end
  1090.  
  1091. function DrawBG()
  1092.   -- Secondary screen background
  1093.   gpu2.setBackground(0xFFFDD0)
  1094.   gpu2.fill(1, 1, 160, 50, " ")
  1095.   gpu2.setBackground(0x000000)
  1096.  
  1097.   -- Primary screen background
  1098.   gpu.setBackground(0xFF65D0)
  1099.   gpu.fill(1, 1, 160, 50, " ")
  1100.   gpu.setBackground(0x000000)
  1101. end
  1102.  
  1103. ----------------------------------------------------------------
  1104. -- Tank bar builders wired to tabs
  1105. ----------------------------------------------------------------
  1106. local tankBarBuffer = 4
  1107.  
  1108. local function make_bank_bars(bankAddresses, startX, startY, g)
  1109.   local bars = {}
  1110.   for i = 1, 9 do
  1111.     local key  = string.format("tank_%02d", i)
  1112.     local y    = startY + tankBarBuffer * (i - 1)
  1113.     local addr = bankAddresses[key]
  1114.     if addr then
  1115.       local b = tankBar.new(startX, y, addr)
  1116.       b.gpu = g
  1117.       if b.progressBar then b.progressBar.gpu = g end
  1118.       b.showLabel = true
  1119.       bars[key] = b
  1120.     end
  1121.   end
  1122.   return bars
  1123. end
  1124.  
  1125. local function build_bank_for_tab(tabIndex, bankAddresses, startX, startY)
  1126.   local bars = make_bank_bars(bankAddresses, startX, startY, gpu2)
  1127.   -- attach each bar to the tab so it's drawn only when that tab is active
  1128.   for i = 1, 9 do
  1129.     local key = string.format("tank_%02d", i)
  1130.     if bars[key] then AddToTab(tabIndex, bars[key]) end
  1131.   end
  1132.   return bars
  1133. end
  1134.  
  1135. -- Build the HX (heat exchanger) buffer tanks into a tab.
  1136. -- Uses same relative coords as bank tabs, so switching tabs keeps layout stable.
  1137. local function build_hx_for_tab(tabIndex, startX, startY)
  1138.   local spacing = tankBarBuffer
  1139.   local bars = {}
  1140.  
  1141.   local function add(key, addr, row)
  1142.     if not addr then return end
  1143.     local b = tankBar.new(startX, startY + spacing * (row - 1), addr)
  1144.     b.gpu = gpu2
  1145.     if b.progressBar then b.progressBar.gpu = gpu2 end
  1146.     b.showLabel = true
  1147.     AddToTab(tabIndex, b)
  1148.     bars[key] = b
  1149.   end
  1150.  
  1151.   -- 4 buffer tanks
  1152.   add("coolIn",  heatExchangerCoolInputBufferTankAdress,  1)
  1153.   add("hotIn",   heatExchangerHotInputBufferTankAdress,   2)
  1154.   add("coolOut", heatExchangerCoolOutputBufferTankAdress, 3)
  1155.   add("hotOut",  heatExchangerHotOutputBufferTankAdress,  4)
  1156.  
  1157.   -- Optional: distiller outputs
  1158.   -- add("distTop",    distillerOutputTankTop,    5)
  1159.   -- add("distBottom", distillerOutputTankBottom, 6)
  1160.  
  1161.   return bars
  1162. end
  1163.  
  1164. ----------------------------------------------------------------
  1165. -- Boot: layout, background, tab content, first paint
  1166. ----------------------------------------------------------------
  1167. LoadScreens()
  1168. DrawBG()
  1169. DrawScreens()
  1170.  
  1171. -- Build content into tabs
  1172. local bars_bank_01 = build_bank_for_tab(1, tanks.bank_01, 5,  8)
  1173. local bars_bank_02 = build_bank_for_tab(2, tanks.bank_02, 5, 8)
  1174. local hx_bars      = build_hx_for_tab(3, 5, 8)
  1175.  
  1176. -- First paint for tabs
  1177. draw_tabbar()
  1178. draw_tabcontent()
  1179.  
  1180. -- First paint for button-panel tabs
  1181. draw_buttonpanel_tabbar()
  1182. draw_buttonpanel_tabcontent()
  1183.  
  1184. term.setCursor(1, 1)
  1185.  
  1186. ----------------------------------------------------------------
  1187. -- Main loop
  1188. ----------------------------------------------------------------
  1189. while true do
  1190.   local ev, a, b, c = event.pull(0.5)
  1191.   if b then
  1192.     gpu.set(1,1,"           ")
  1193.     gpu.set(1,1, "x:"..b.." y:"..c)
  1194.   end
  1195.   -- handle buttons on primary screen
  1196.   for i = 1, #primaryScreenChildren do
  1197.     local el = primaryScreenChildren[i]
  1198.     if el and el.type == "button" and el.handle then
  1199.       el:handle(ev, a, b, c)
  1200.     end
  1201.   end
  1202.  
  1203.   -- handle elements on secondary screen (includes tab buttons + panel tab buttons)
  1204.   for i = 1, #secondaryScreenChildren do
  1205.     local el = secondaryScreenChildren[i]
  1206.     if el and el.type == "button" and el.handle then
  1207.       el:handle(ev, a, b, c)
  1208.     end
  1209.   end
  1210.  
  1211.   -- handle ACTIVE button-panel tab contents (so only visible tab’s controls react)
  1212.   do
  1213.     local list = ButtonTabContent[btnCurrentTab]
  1214.     if list then
  1215.       for i = 1, #list do
  1216.         local el = list[i]
  1217.         if el and el.type == "button" and el.handle then
  1218.           el:handle(ev, a, b, c)
  1219.         end
  1220.       end
  1221.     end
  1222.   end
  1223.  
  1224.   -- periodic UI updates if needed
  1225.    --UpdateScreens()
  1226.  
  1227.   os.sleep(0.5)
  1228. end
  1229.  
Add Comment
Please, Sign In to add comment