GT New Horizons · OpenComputers
OpenComputers Space Pumping
These OpenComputers (OC) scripts automatically switch Space Elevator (SE) pumping module settings based on which fluids are needed at the time, similar to a level maintainer. This saves from having to manually change the settings all the time, or creating dedicated modules for each fluid. This guide walks through every step of the process, from building the setup to debugging and troubleshooting. No prior knowledge of OC is necessary.
The general idea is that the script queries an AE2 subnetwork to compare the current fluid levels against the configured target levels. If any are below the minimum threshold, then the script finds an available pumping module to change the gas, planet, and batch size parameters. It calculates the exact length of time needed to reach the target level based on the tier of the module and the fluid itself. Once all target levels are reached, the script enters a sleep mode until it is needed again. The player only ever needs to change the configuration settings at the top of the script.
Building the Setup
| STEP 1 | |
| Build out the fluid subnetwork (blue) with an ME controller and ME drive. Connect as many ME output haches from as many pumping modules as preferred, although 1-3 is usually enough.
Insert fluid storage cells into the ME drive to hold the full capacity of the SE fluids for the main network, since they are stored locally. Only 40 types are needed for all the different fluids, but there could be additional ME drives with even more cells. Optionally, add a fluid terminal to view the current fluid levels in the subnetwork. |
![]() |
| STEP 2 | |
| Use adapters to connect to the pumping modules. They can either touch the controllers directly, or use an MFU to wirelessly connect. Link the adapters together with OpenComputers cable.
To use an MFU, sneak right-click one of the controllers and then insert the upgrade into one of the adapters. It should highlight the block that is selected when holding the MFU in hand. The maximum range of the MFU is 16 blocks so the adapters do not have to in these exact locations, but it is important that one also touches the ME controller of the fluid subnetwork (blue). Adapters can connect to multiple components at the same time. |
![]() |
| STEP 3 | |
| Connect a screen (Tier 3), computer case (Tier 3), and keyboard to the adapters in the previous step. The components just need to be touching to work.
Insert the bare minimum components into the computer case. These could be even lower tier but there is no reason not to use the best components.
Power the computer with an AE2 cable or neutronium energy cell. |
![]() |
| STEP 4 | |
| Place an ME dual interface on the fluid subnetwork (blue) with default settings facing into an ME fluid storage bus on the main network (green).
This lets the main network use all the fluids on the fluid subnetwork as if they were stored on the main network itself. If the direction of the ME fluid storage bus is EXTRACT ONLY then the main network may randomly use extra types for the same fluids. If the direction of the ME fluid storage bus is BIDIRECTIONAL then the main network may store random fluids on the fluid subnetwork and clog it. In that case, partition the storage cells to the SE fluids. |
![]() |
| STEP 5 | |
| After booting up the computer, follow the commands on screen to install OpenOS.
Create a new script by typing Edit the config as necessary. Press CTRL+S to save and CTRL+W to exit. Use the same edit command to change the code at anytime. Launch the script by typing |
![]() |
Option 1: Target Levels
This version of the script uses specified target levels for each of the fluids. This allows less desirable fluids to be capped at a lower amount or even blacklisted to maximize time and energy for more desirable fluids. Priority is based on the percentage to target level and the priority setting, as seen in the following equation. This means empty fluids are prioritized first and those with a lower priority setting can still take priority if their percentage to target level is low enough. The target level can be set really high and hardly ever needs to change since all fluid levels rise together.

-- GTNH 2.9 Space Pumping (Fox, samsonsin, San32)
local component = require('component')
local thread = require('thread')
local event = require('event')
local term = require('term')
local me = component.me_controller
local pumps = {}
-- CTRL+C to stop the script at any time, or restart the computer.
-- ===================== CONFIG ======================
-- Only change the PRIORITY and TARGET values. Do not change the SETTING or RATE values.
-- Quantum = 270e9 || Digital Singularity = 4e18 || Artificial Universe = 9e18
local master = {
-- Planet 2 -----------------------------------------------------------------------------
['Chlorobenzene'] = {target=10e9, priority=1, setting={2,1}, rate=896000}, -- Gas 1
-- Planet 3 -----------------------------------------------------------------------------
['Ender Goo'] = {target=10e9, priority=1, setting={3,1}, rate=32000}, -- Gas 1
['Very Heavy Oil'] = {target=0, priority=1, setting={3,2}, rate=1400000}, -- Gas 2
['Lava'] = {target=10e9, priority=1, setting={3,3}, rate=1800000}, -- Gas 3
['Natural Gas'] = {target=0, priority=1, setting={3,4}, rate=1400000}, -- Gas 4
-- Planet 4 -----------------------------------------------------------------------------
['Sulfuric Acid'] = {target=10e9, priority=1, setting={4,1}, rate=784000}, -- Gas 1
['Molten Iron'] = {target=10e9, priority=2, setting={4,2}, rate=896000}, -- Gas 2
['Oil'] = {target=10e9, priority=1, setting={4,3}, rate=1400000}, -- Gas 3
['Heavy Oil'] = {target=0, priority=1, setting={4,4}, rate=1792000}, -- Gas 4
['Molten Lead'] = {target=10e9, priority=1, setting={4,5}, rate=896000}, -- Gas 5
['Raw Oil'] = {target=0, priority=1, setting={4,6}, rate=1400000}, -- Gas 6
['Light Oil'] = {target=0, priority=1, setting={4,7}, rate=780000}, -- Gas 7
['Carbon Dioxide'] = {target=1e9, priority=1, setting={4,8}, rate=1680000}, -- Gas 8
-- Planet 5 -----------------------------------------------------------------------------
['Carbon Monoxide'] = {target=10e9, priority=1, setting={5,1}, rate=4480000}, -- Gas 1
['Helium-3'] = {target=10e9, priority=1, setting={5,2}, rate=2800000}, -- Gas 2
['Salt Water'] = {target=10e9, priority=1, setting={5,3}, rate=2800000}, -- Gas 3
['Helium'] = {target=10e9, priority=3, setting={5,4}, rate=1400000}, -- Gas 4
['Liquid Oxygen'] = {target=0, priority=1, setting={5,5}, rate=896000}, -- Gas 5
['Neon'] = {target=1e9, priority=1, setting={5,6}, rate=32000}, -- Gas 6
['Argon'] = {target=1e9, priority=1, setting={5,7}, rate=32000}, -- Gas 7
['Krypton'] = {target=1e9, priority=1, setting={5,8}, rate=8000}, -- Gas 8
['Methane'] = {target=1e9, priority=1, setting={5,9}, rate=1792000}, -- Gas 9
['Hydrogen Sulfide'] = {target=0, priority=1, setting={5,10}, rate=392000}, -- Gas 10
['Ethane'] = {target=0, priority=1, setting={5,11}, rate=1194000}, -- Gas 11
-- Planet 6 -----------------------------------------------------------------------------
['Deuterium'] = {target=10e9, priority=1, setting={6,1}, rate=1568000}, -- Gas 1
['Tritium'] = {target=10e9, priority=1, setting={6,2}, rate=240000}, -- Gas 2
['Ammonia'] = {target=10e9, priority=2, setting={6,3}, rate=240000}, -- Gas 3
['Xenon'] = {target=10e9, priority=2, setting={6,4}, rate=16000}, -- Gas 4
['Ethylene'] = {target=10e9, priority=1, setting={6,5}, rate=1792000}, -- Gas 5
-- Planet 7 -----------------------------------------------------------------------------
['Hydrofluoric Acid'] = {target=10e9, priority=1, setting={7,1}, rate=672000}, -- Gas 1
['Fluorine'] = {target=10e9, priority=1, setting={7,2}, rate=1792000}, -- Gas 2
['Nitrogen'] = {target=10e9, priority=3, setting={7,3}, rate=1792000}, -- Gas 3
['Oxygen'] = {target=10e9, priority=3, setting={7,4}, rate=1729000}, -- Gas 4
-- Planet 8 -----------------------------------------------------------------------------
['Hydrogen'] = {target=10e9, priority=3, setting={8,1}, rate=1568000}, -- Gas 1
['Liquid Air'] = {target=0, priority=1, setting={8,2}, rate=875000}, -- Gas 2
['Molten Copper'] = {target=10e9, priority=2, setting={8,3}, rate=672000}, -- Gas 3
['Unknown Liquid'] = {target=10e9, priority=1, setting={8,4}, rate=672000}, -- Gas 4
['Distilled Water'] = {target=10e9, priority=1, setting={8,5}, rate=17920000}, -- Gas 5
['Radon'] = {target=1e9, priority=1, setting={8,6}, rate=64000}, -- Gas 6
['Molten Tin'] = {target=10e9, priority=1, setting={8,7}, rate=672000}} -- Gas 7
-- The % of the Target when Considered Complete (Default: 95%)
local threshold = 0.95
-- The Upper Limit on the Duration of an Iteration (Default: 30s)
local maxBatchSize = 30
-- The Text Color (Default: '\27[1;36m')
local color = '\27[1;36m'
-- (https://github.com/torch/sys/blob/master/colors.lua)
-- Cyan = '\27[1;36m' || Green = '\27[1;32m' || Red = '\27[0;31m' || Magenta = '\27[0;35m'
-- =================== END CONFIG ====================
local function findPumps()
for address in component.list('gt_machine') do
local module = component.proxy(address)
local name = module.getName()
if name == "projectmodulepumpt1" then
table.insert(pumps, {module=module, threads=1, mult=4, priority=1, fluid=nil, amount=0})
elseif name == "projectmodulepumpt2" then
table.insert(pumps, {module=module, threads=4, mult=16, priority=2, fluid=nil, amount=0})
elseif name == "projectmodulepumpt3" then
table.insert(pumps, {module=module, threads=4, mult=256, priority=3, fluid=nil, amount=0})
end
end
-- Sort Based on Priority
table.sort(pumps, function(a, b) return a.priority > b.priority end)
end
local function updateFluids()
-- Reset Everything to Zero
local lowFluids = {}
for _, fluid in pairs(master) do fluid.amount = 0 end
-- Update Fluids from ME Network
for _, fluid in ipairs(me.getFluidsInNetwork()) do
if master[fluid.label] ~= nil then master[fluid.label].amount = fluid.size end
end
-- Update Fluids from Pumps
for _, pump in ipairs(pumps) do
if pump.fluid ~= nil then master[pump.fluid].amount = master[pump.fluid].amount + pump.amount end
end
-- Identify Low Fluids
for _, fluid in pairs(master) do
if fluid.amount < threshold * fluid.target then table.insert(lowFluids, fluid) end
end
return lowFluids
end
local function updatePumps(lowFluids)
for _, pump in ipairs(pumps) do
-- Ensure Pump is Disabled
pump.module.setWorkAllowed(false)
while pump.module.isMachineActive() do os.sleep(2) end
pump.fluid, pump.amount = nil, 0
-- Sort Low Fluids based on Priority and % of Target
table.sort(lowFluids, function(a, b)
return (1 - (a.amount / a.target) ^ a.priority) < (1 - (b.amount / b.target) ^ b.priority)
end)
local fluid = lowFluids[#lowFluids]
if fluid ~= nil then
-- Change Planet and Gas for all Threads
for i=0, pump.threads-1 do
pump.module.setParameter('recipe' .. i .. '.planetType', fluid.setting[1])
pump.module.setParameter('recipe' .. i .. '.gasType', fluid.setting[2])
end
-- Change Batch Size based on Distance from Target
local batchSize = math.min(maxBatchSize, math.ceil((fluid.target - fluid.amount) / (fluid.rate * pump.mult)))
pump.module.setParameter('batch', batchSize)
print(string.format('autoPump: Running %s for %d Seconds', fluid.label, batchSize))
-- Preemptively Update Fluid Amount
pump.fluid = fluid.label
pump.amount = batchSize * fluid.rate * pump.mult
fluid.amount = fluid.amount + pump.amount
-- Remove Fluid if above Target Threshold
if fluid.amount >= fluid.target * threshold then table.remove(lowFluids) end
-- Run Once
pump.module.setWorkAllowed(true)
os.sleep(0.1)
pump.module.setWorkAllowed(false)
else
return
end
end
end
local function parse(label)
local fluid = master[label]
if fluid.target == 0 then
return string.format('[----------] %-20s', fluid.label)
else
local percent = math.min(10, math.ceil(10 * (fluid.amount / fluid.target)))
return string.format('[%s%s] %-20s', color .. string.rep('■', percent) .. '\27[0m', string.rep('□', 10-percent), fluid.label)
end
end
local function printDashboard()
term.clear()
print('\n┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐')
print('│' .. color .. ' Space Elevator Fluid Levels (% of Target)' .. '\27[0m' .. string.rep(' ', 95) .. '│')
print('├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤')
print(string.format('│ %s %s %s %s │', parse('Hydrogen'), parse('Argon'), parse('Oil'), parse('Hydrogen Sulfide')))
print(string.format('│ %s %s %s %s │', parse('Helium'), parse('Radon'), parse('Raw Oil'), parse('Sulfuric Acid')))
print(string.format('│ %s %s %s %s │', parse('Nitrogen'), parse('Neon'), parse('Light Oil'), parse('Hydrofluoric Acid')))
print(string.format('│ %s %s %s %s │', parse('Oxygen'), parse('Krypton'), parse('Heavy Oil'), string.rep(' ', 33)))
print(string.format('│ %s %s %s %s │', parse('Fluorine'), parse('Xenon'), parse('Natural Gas'), string.rep(' ', 33)))
print(string.format('│ %s %s %s %s │', string.rep(' ', 33), string.rep(' ', 33), string.rep(' ', 33), string.rep(' ', 33)))
print(string.format('│ %s %s %s %s │', parse('Molten Iron'), parse('Ammonia'), parse('Distilled Water'), parse('Helium-3')))
print(string.format('│ %s %s %s %s │', parse('Molten Copper'), parse('Ethylene'), parse('Salt Water'), parse('Deuterium')))
print(string.format('│ %s %s %s %s │', parse('Molten Tin'), parse('Ethane'), parse('Chlorobenzene'), parse('Tritium')))
print(string.format('│ %s %s %s %s │', parse('Molten Lead'), parse('Methane'), parse('Unknown Liquid'), string.rep(' ', 33)))
print(string.format('│ %s %s %s %s │', string.rep(' ', 33), string.rep(' ', 33), string.rep(' ', 33), string.rep(' ', 33)))
print(string.format('│ %s %s %s %s │', parse('Liquid Air'), parse('Carbon Monoxide'), parse('Lava'), string.rep(' ', 33)))
print(string.format('│ %s %s %s %s │', parse('Liquid Oxygen'), parse('Carbon Dioxide'), parse('Ender Goo'), string.rep(' ', 33)))
print('└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘\n')
end
local keyHandler = thread.create(function()
local keyboard = require('keyboard')
while true do
_, _, _, code, _ = event.pull('key_down')
if code == keyboard.keys.p then printDashboard()
elseif code == keyboard.keys.u then
pumps = {}
findPumps()
end
end
end)
-- ====================== MAIN =======================
local main = thread.create(function()
local n = 1
findPumps()
for k, fluid in pairs(master) do fluid.label = k end
-- THE LOOP
while true do
-- Update Fluid Amounts
local lowFluids = updateFluids()
if next(lowFluids) ~= nil then
if n % 5 == 1 then printDashboard() end
-- Update Pump Settings
updatePumps(lowFluids)
n = n+1
elseif n > 0 then
-- Reset Pump Settings
for _, pump in ipairs(pumps) do
pump.fluid, pump.amount = nil, 0
end
-- Nothing to Update, Sleep 3 Minutes
printDashboard()
print('autoPump: Sleeping...\n')
os.sleep(180)
n=0
end
end
end)
local cleanUp = thread.create(function()
event.pull('interrupted')
term.clear()
print('Received Exit Command!')
for _, pump in ipairs(pumps) do
for _=1, pump.threads do pump.module.setWorkAllowed(false) end
end
main.kill()
keyHandler.kill()
os.exit(0)
end)
thread.waitForAny({main, keyHandler, cleanUp})
os.exit(0)
Option 2: Median and Offset
This version of the script takes the median value of the current fluid levels and adds an offset to determine the target level for all fluids, as seen in the following equation. This means the target level never has to be manually set and dynamically changes with the current fluid levels. However, there is no capping undesirable fluids at a lower amount or blacklisting them. Priority is based first on the priority setting and then the percentage to the target level. All fluid levels rise together until they reach the max storage size (configurable) which by default is 99% of a fluid digital singularity storage cell.

-- GTNH 2.9 Space Pumping (Fox, samsonsin)
local component = require('component')
local me = component.me_controller
local pumps = {}
local n = 0
-- CTRL+ALT+C to stop the script at any time.
-- ===================== CONFIG ======================
-- Only change the PRIORITY value. Do not change the SETTING or RATE values.
local master = {
-- Planet 2 -----------------------------------------------------------------------------
['Chlorobenzene'] = {priority=0, amount=0, setting={2,1}, rate=896000}, -- Gas 1
-- Planet 3 -----------------------------------------------------------------------------
['Ender Goo'] = {priority=0, amount=0, setting={3,1}, rate=32000}, -- Gas 1
['Very Heavy Oil'] = {priority=0, amount=0, setting={3,2}, rate=1400000}, -- Gas 2
['Lava'] = {priority=0, amount=0, setting={3,3}, rate=1800000}, -- Gas 3
['Natural Gas'] = {priority=0, amount=0, setting={3,4}, rate=1400000}, -- Gas 4
-- Planet 4 -----------------------------------------------------------------------------
['Sulfuric Acid'] = {priority=0, amount=0, setting={4,1}, rate=784000}, -- Gas 1
['Molten Iron'] = {priority=0, amount=0, setting={4,2}, rate=896000}, -- Gas 2
['Oil'] = {priority=0, amount=0, setting={4,3}, rate=1400000}, -- Gas 3
['Heavy Oil'] = {priority=0, amount=0, setting={4,4}, rate=1792000}, -- Gas 4
['Molten Lead'] = {priority=0, amount=0, setting={4,5}, rate=896000}, -- Gas 5
['Raw Oil'] = {priority=0, amount=0, setting={4,6}, rate=1400000}, -- Gas 6
['Light Oil'] = {priority=0, amount=0, setting={4,7}, rate=780000}, -- Gas 7
['Carbon Dioxide'] = {priority=0, amount=0, setting={4,8}, rate=1680000}, -- Gas 8
-- Planet 5 -----------------------------------------------------------------------------
['Carbon Monoxide'] = {priority=0, amount=0, setting={5,1}, rate=4480000}, -- Gas 1
['Helium-3'] = {priority=0, amount=0, setting={5,2}, rate=2800000}, -- Gas 2
['Salt Water'] = {priority=0, amount=0, setting={5,3}, rate=2800000}, -- Gas 3
['Helium'] = {priority=0, amount=0, setting={5,4}, rate=1400000}, -- Gas 4
['Liquid Oxygen'] = {priority=0, amount=0, setting={5,5}, rate=896000}, -- Gas 5
['Neon'] = {priority=0, amount=0, setting={5,6}, rate=32000}, -- Gas 6
['Argon'] = {priority=0, amount=0, setting={5,7}, rate=32000}, -- Gas 7
['Krypton'] = {priority=0, amount=0, setting={5,8}, rate=8000}, -- Gas 8
['Methane'] = {priority=0, amount=0, setting={5,9}, rate=1792000}, -- Gas 9
['Hydrogen Sulfide'] = {priority=0, amount=0, setting={5,10}, rate=392000}, -- Gas 10
['Ethane'] = {priority=0, amount=0, setting={5,11}, rate=1194000}, -- Gas 11
-- Planet 6 -----------------------------------------------------------------------------
['Deuterium'] = {priority=0, amount=0, setting={6,1}, rate=1568000}, -- Gas 1
['Tritium'] = {priority=0, amount=0, setting={6,2}, rate=240000}, -- Gas 2
['Ammonia'] = {priority=0, amount=0, setting={6,3}, rate=240000}, -- Gas 3
['Xenon'] = {priority=0, amount=0, setting={6,4}, rate=16000}, -- Gas 4
['Ethylene'] = {priority=0, amount=0, setting={6,5}, rate=1792000}, -- Gas 5
-- Planet 7 -----------------------------------------------------------------------------
['Hydrofluoric Acid'] = {priority=0, amount=0, setting={7,1}, rate=672000}, -- Gas 1
['Fluorine'] = {priority=0, amount=0, setting={7,2}, rate=1792000}, -- Gas 2
['Nitrogen'] = {priority=0, amount=0, setting={7,3}, rate=1792000}, -- Gas 3
['Oxygen'] = {priority=0, amount=0, setting={7,4}, rate=1729000}, -- Gas 4
-- Planet 8 -----------------------------------------------------------------------------
['Hydrogen'] = {priority=0, amount=0, setting={8,1}, rate=1568000}, -- Gas 1
['Liquid Air'] = {priority=0, amount=0, setting={8,2}, rate=875000}, -- Gas 2
['Molten Copper'] = {priority=0, amount=0, setting={8,3}, rate=672000}, -- Gas 3
['Unknown Liquid'] = {priority=0, amount=0, setting={8,4}, rate=672000}, -- Gas 4
['Distilled Water'] = {priority=0, amount=0, setting={8,5}, rate=17920000}, -- Gas 5
['Radon'] = {priority=0, amount=0, setting={8,6}, rate=64000}, -- Gas 6
['Molten Tin'] = {priority=0, amount=0, setting={8,7}, rate=672000}} -- Gas 7
local target = 1
local dynamicTargetOffset = 10e9 -- adds to the median fluid amount to set as the target
local singularityCellSize = 4.61e18
local maxStorageAmount = singularityCellSize*0.99
-- The Upper Limit on the Duration of an Iteration (Default: 30s)
local maxBatchSize = 30
-- =================== END CONFIG ====================
local function sortFluidsByPriorityThenFillRatio(lowFluids)
table.sort(lowFluids, function(a, b)
if a.priority - b.priority ~= 0 then
return a.priority > b.priority
else
return (a.amount / target) < (b.amount / target)
end
end)
end
local function sortFluidsByAmount(lowFluids)
table.sort(lowFluids, function(a, b)
return a.amount < b.amount
end)
end
local function formatFluid(amount)
local suffixes = {' ', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'}
local index = 1
local value = amount
while value >= 1000 and index < #suffixes do
value = value / 1000
index = index + 1
end
return string.format('%.3f %sL', value, suffixes[index])
end
local function findPumps()
for address in component.list('gt_machine') do
local module = component.proxy(component.get(address))
local name = module.getName()
if name == "projectmodulepumpt1" then
table.insert(pumps, {module=module, threads=1, mult=4, priority=1})
elseif name == "projectmodulepumpt2" then
table.insert(pumps, {module=module, threads=4, mult=16, priority=2})
elseif name == "projectmodulepumpt3" then
table.insert(pumps, {module=module, threads=4, mult=256, priority=3})
end
end
-- Sort Based on Priority
table.sort(pumps, function(a, b) return a.priority > b.priority end)
end
local function updateFluids()
-- Reset Everything to Zero
local lowFluids = {}
for _, fluid in pairs(master) do
fluid.amount = 0
end
-- Update the Fluids Available
for _, fluid in ipairs(me.getFluidsInNetwork()) do
if master[fluid.label] ~= nil then
master[fluid.label].amount = fluid.size
end
end
-- Convert master dictionary to array for sorting
local fluidArray = {}
for _, fluid in pairs(master) do
table.insert(fluidArray, fluid)
end
-- Find Median to set dynamic target
sortFluidsByAmount(fluidArray)
local medianFluid = #fluidArray > 0 and fluidArray[math.ceil(#fluidArray / 2)] or nil
target = medianFluid ~= nil and math.min(medianFluid.amount + dynamicTargetOffset, maxStorageAmount) or maxStorageAmount
print('┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐')
print(string.format('│ Target set according to Median: │ %-20s │ %10s + %10s = %10s %51s', medianFluid.label, formatFluid(medianFluid.amount), formatFluid(dynamicTargetOffset), formatFluid(target), '│'))
print('├──────────────────────┬───────┬────────────────────────────────────────────────────────────────┬───────────────────────────────┬───────────────┤')
print('│ Name │ Dur │ Old + Added = New : Target +% = Target % │ +% │ L/s │')
print('├──────────────────────┼───────┼────────────────────────────────────────────────────────────────┼───────────────────────────────┼───────────────┤')
-- Identify Low Fluids
for _, fluid in pairs(master) do
if fluid.amount < target then
table.insert(lowFluids, fluid)
end
end
return lowFluids
end
local function updatePumps(lowFluids)
for _, pump in ipairs(pumps) do
-- Ensure Pump is Disabled
pump.module.setWorkAllowed(false)
while pump.module.isMachineActive() do os.sleep(2) end
sortFluidsByPriorityThenFillRatio(lowFluids)
local fluid = lowFluids[1]
if fluid ~= nil then
-- Ensure pump is disabled
while pump.module.isMachineActive() do os.sleep(1) end
-- Remove fluid if already at target. next fluid will be at position 1 after removal
if lowFluids[1].amount >= target then
table.remove(lowFluids, 1)
end
-- Change planet and gas for ALL threads
for i=0, pump.threads-1 do
pump.module.setParameter('recipe' .. i .. '.planetType', fluid.setting[1])
pump.module.setParameter('recipe' .. i .. '.gasType', fluid.setting[2])
end
-- Calculate varous amounts, update fluid amount preemptively
local batchSize = math.min(maxBatchSize, math.ceil((maxStorageAmount - fluid.amount) / (fluid.rate * pump.mult)))
local oldAmount = fluid.amount
fluid.amount = fluid.amount + (batchSize * fluid.rate * pump.mult)
local percentageGain = oldAmount > 0 and ((fluid.amount - oldAmount) / oldAmount) * 100 or 0
local targetPercentageGain = target > 0 and ((fluid.amount - oldAmount) / target) * 100 or 0
local targetFillPercentage = (fluid.amount / target) * 100
print(string.format('│ %-20s │ %3d s │ %10s + %10s = %10s : %+8.3f %% = %8.3f %% │ %+27.3f %% │ %8.3f ML/s │',
fluid.label,
batchSize,
formatFluid(oldAmount),
formatFluid((fluid.amount - oldAmount)),
formatFluid(fluid.amount),
targetPercentageGain,
targetFillPercentage,
percentageGain,
(fluid.amount - oldAmount)/1e6/batchSize))
pump.module.setParameter('batch', batchSize)
-- Run once
pump.module.setWorkAllowed(true)
os.sleep(0.1)
pump.module.setWorkAllowed(false)
else
return
end
end
print('└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘')
end
-- ====================== MAIN =======================
local function main()
print('autoPump: Reading Config... Scanning Pumps...')
findPumps()
for k, fluid in pairs(master) do
fluid.label = k
end
-- THE LOOP
while true do
-- Update Fluid Amounts
local lowFluids = updateFluids()
-- Update Pump Settings
if next(lowFluids) ~= nil then
updatePumps(lowFluids)
n=0
-- Nothing to Update, Sleep 3 Minutes
elseif n==0 then
print('autoPump: Sleeping...\n')
os.sleep(180)
n=1
end
end
end
main()
Running the Scripts
In both versions, the script autoPump first identifies all connected pumps. The tier of the pumps do not all have to be the same, and higher tiers are automatically prioritized over lower ones. Next, the script identifies any low fluids by querying the fluid subnetwork and comparing the current fluid levels against the target level, whether set manually or by using the median and offset. A fluid subnetwork is used to reduce the query size and save TPS. If any fluids are below the target value, then the script finds an available pumping module to change the gas, planet, and batch size parameters.
The batch size is calculated based on the length of time needed to reach the target level which depends on the tier of the module and the fluid itself. The maximum batch size is 30 (configurable) to prevent fluid pumps from running for a very long time without producing anything. Every "recipe" is exactly 1 second long so the maximum batch size is equivalent to the maximum duration in seconds.
Once all target levels are reached, or exceed the maximum storage size, the computer enters a sleep mode until it is needed again. By default, the script queries the fluid subnetwork once every 3 minutes to see if anything has changed. To run autoPump, simply enter:
autoPump
Note that the pumps can only change settings while idle. Ensure that they are not actively running prior to launching the script, or manually enabled during the script. To stop the script, simply restart the computer or press CTRL+ALT+C at any time. Changing anything in the config does NOT require a restart since it is all within a single file.
The target level version of the script has two additional keybinds. Pressing "u" updates the registered pumps which allows more to be added without ever stopping the program. Pressing "p" updates the dashboard and re-prints it immediately.
Pumping Modules & Fluids
There are three tiers of Pumping Modules available. Higher tiers offer more parallels and the ability to run multiple recipes (threads) simultaneously. Threads do not need to run the same recipe, but the script guarantees that they do. All three tiers have access to every possible fluid and gas. The modules do not overclock, but they only require a minimum EU/t to run--the voltage is irrelevant. Parallels process the same fluid and multiply the power requirement.
| Module | Requires | Threads | Parallels per Thread | Max Power |
| Space Pumping MK-I | Motor MK-II | 1 | 4 | 7,864,320 EU/t |
| Space Pumping MK-II | Motor MK-III | 4 | 4 | 31,457,280 EU/t |
| Space Pumping MK-III | Motor MK-IV | 4 | 64 | 503,316,480 EU/t |
The following table is the full list of planet types, gas types, fluids, and pumping speeds for various amounts of parallels. The script already includes these setting and rate values in the code.
| Planet Type | Gas Type | Fluid | Base (L/s) | 4 Parallels (L/s) | 64 Parallels (L/s) |
| 2 | 1 | Chlorobenzene | 896,000 | 3,584,000 | 57,344,000 |
| 3 | 1 | Ender Goo | 32,000 | 128,000 | 2,048,000 |
| 2 | Very Heavy Oil | 1,400,000 | 5,600,000 | 89,600,000 | |
| 3 | Lava | 1,800,000 | 7,200,000 | 115,200,000 | |
| 4 | Natural Gas | 1,400,000 | 5,600,000 | 89,600,000 | |
| 4 | 1 | Sulfuric Acid | 784,000 | 3,136,000 | 50,176,000 |
| 2 | Molten Iron | 896,000 | 3,584,000 | 57,344,000 | |
| 3 | Oil | 1,400,000 | 5,600,000 | 89,600,000 | |
| 4 | Heavy Oil | 1,792,000 | 7,168,000 | 114,688,000 | |
| 5 | Molten Lead | 896,000 | 3,584,000 | 57,344,000 | |
| 6 | Raw Oil | 1,400,000 | 5,600,000 | 89,600,000 | |
| 7 | Light Oil | 780,000 | 3,120,000 | 49,920,000 | |
| 8 | CO2 Gas | 1,680,000 | 6,720,000 | 107,520,000 | |
| 5 | 1 | Carbon Monoxide | 4,480,000 | 17,920,000 | 286,720,000 |
| 2 | Helium-3 | 2,800,000 | 11,200,000 | 179,200,000 | |
| 3 | Salt Water | 2,800,000 | 11,200,000 | 179,200,000 | |
| 4 | Helium | 1,400,000 | 5,600,000 | 89,600,000 | |
| 5 | Liquid Oxygen | 896,000 | 3,584,000 | 57,344,000 | |
| 6 | Neon | 32,000 | 128,000 | 2,048,000 | |
| 7 | Argon | 32,000 | 128,000 | 2,048,000 | |
| 8 | Krypton | 8,000 | 32,000 | 512,000 | |
| 9 | Methane | 1,792,000 | 7,168,000 | 114,688,000 | |
| 10 | Hydrogen Sulfide | 392,000 | 1,568,000 | 25,088,000 | |
| 11 | Ethane | 1,194,000 | 4,776,000 | 76,416,000 | |
| 6 | 1 | Deuterium | 1,568,000 | 6,272,000 | 100,352,000 |
| 2 | Tritium | 240,000 | 960,000 | 15,360,000 | |
| 3 | Ammonia | 240,000 | 960,000 | 15,360,000 | |
| 4 | Xenon | 16,000 | 64,000 | 1,024,000 | |
| 5 | Ethylene | 1,792,000 | 7,168,000 | 114,688,000 | |
| 7 | 1 | Hydrofluoric Acid | 672,000 | 2,688,000 | 32,008,000 |
| 2 | Fluorine | 1,792,000 | 7,168,000 | 114,688,000 | |
| 3 | Nitrogen | 1,792,000 | 7,168,000 | 114,688,000 | |
| 4 | Oxygen | 1,792,000 | 7,168,000 | 114,688,000 | |
| 8 | 1 | Hydrogen | 1,568,000 | 6,272,000 | 100,352,000 |
| 2 | Liquid Air | 875,000 | 3,500,000 | 56,000,000 | |
| 3 | Molten Copper | 672,000 | 2,688,000 | 32,008,000 | |
| 4 | Unknown Liquid | 672,000 | 2,688,000 | 32,008,000 | |
| 5 | Distilled Water | 17,920,000 | 71,680,000 | 1,146,880,000 | |
| 6 | Radon | 64,000 | 256,000 | 4,096,000 | |
| 7 | Molten Tin | 672,000 | 2,688,000 | 32,008,000 | |
Other Helpful Commands
To list all of the files installed on the computer, enter
ls
To edit (or create) a new file, enter
edit <filename>.lua
To remove any one file installed on the computer, enter
rm <filename>
To view an entire message regardless of how long it may be, enter
<program> 2>/errors.log
edit /errors.log
Thanks
Huge thanks to Recursive Pineapple for their initial implementation and inspiration! Also big thanks to samsonsin for helping improve the script and designing the median + offset version!




