diff --git a/Maintainer.lua b/Maintainer.lua index 5a78c47..78ced9c 100644 --- a/Maintainer.lua +++ b/Maintainer.lua @@ -3,17 +3,37 @@ local cfg = require("config") local util = require("src.Utility") local items = cfg.items +local fluids = cfg.fluids local sleepInterval = cfg.sleep - + +if fluids and next(fluids) ~= nil and not ae2.hasFluidSupport() then + logInfo("WARNING: cfg.fluids is configured but the ME interface does not expose getFluidInNetwork (requires GTNH 2.9+). Fluid entries will be skipped.") + fluids = nil +end + while true do local itemsCrafting = ae2.checkIfCrafting() - + for item, config in pairs(items) do - if itemsCrafting[item] ~= true then - local success, answer = ae2.requestItem(item, config[1], config[2]) + if itemsCrafting[item] == true then + logInfo(item .. " is already being crafted, skipping...") + else + local success, answer = ae2.requestItem(item, config[1], config[2], config[3]) logInfo(answer) end - + + end + + if fluids then + for fluid, config in pairs(fluids) do + if itemsCrafting[fluid] == true then + logInfo(fluid .. " is already being crafted, skipping...") + else + local success, answer = ae2.requestFluid(fluid, config[1], config[2], config[3]) + logInfo(answer) + end + end end + os.sleep(sleepInterval) -end +end \ No newline at end of file diff --git a/README.md b/README.md index 1e45f52..5332149 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,56 @@ # Infinite Maintainer + Lets you passive lines easily, without lag and randomness of AE2 maintainer. Also supports having a threshold. # Setup + - Full block ME interface connected to an adapter - Crafting Monitors on your CPUs - (Internet card) - OC stuff to make a basic computer # Installation + Download it + ```bash -wget https://raw.githubusercontent.com/Niels1006/Infinite-Maintainer/master/installer.lua && installer +wget raw.githubusercontent.com/Echoloquate/Level-Maintainer/master/installer.lua && installer ``` Run it + ```bash Maintainer ``` # Config -You can change maintained items in `config.lua`. Pattern is as follows: `["item_name"] = {threshold, batch_size}` as well as the time inbetween craft checks. -**!! Keep in mind that threshold should only be added if necessary and preferrably not in mainnet, since it has a performance impact !!** +You can change maintained items in `config.lua`. There are two blocks: `cfg.items` for regular items (and the legacy `ae2fc:fluid_drop` workaround) and `cfg.fluids` for native fluid maintenance on GTNH 2.9+. + +## Items + +```lua +cfg["items"] = { + ["Osmium Dust"] = {nil, 64}, -- no threshold + ["drop of Molten SpaceTime"] = {1000000, 1, "spacetime"}, -- fluid drop with threshold + fluid name +} +``` + +Pattern: `["item_label"] = {threshold, batch_size, fluid_name?}`. The third value is only needed for `ae2fc:fluid_drop` items and is the fluid's registry name -- this path works on any GTNH version. + +## Fluids (GTNH 2.9+) + +GTNH 2.9 unified items and fluids in the OpenComputers AE2 integration, so fluid craftables can now be requested directly without going through `ae2fc:fluid_drop`. Threshold checks use real fluid amounts in mB. + +```lua +cfg["fluids"] = { + ["Molten SpaceTime"] = {1000000, 1000}, +} +``` + +Pattern: `["fluid_label"] = {threshold_mb, batch_mb[, fluid_registry_name]}`. The label is the fluid's display name as shown in the AE crafting terminal. The fluid registry name is auto-detected from the craftable's stack -- pass it as a third value only as an override if auto-detection ever resolves to the wrong fluid. Omit the block entirely on pre-2.9 setups. + +**!! Threshold has a performance impact -- only add it when necessary, and preferably not on mainnet !!** Reboot after changing values. diff --git a/config.lua b/config.lua index 42d8b31..0820bda 100644 --- a/config.lua +++ b/config.lua @@ -2,15 +2,26 @@ local cfg = {} -- EXAMPLE -- --- [item_name] = {threshold, batch_size} -- keep in mind that no threshold has a better performance! --- ["Osmium Dust"] = {nil, 64} -- without threshold, batch_size=64 --- ["drop of Molten SpaceTime"] = {1000000, 1} -- with threshold +-- [item_name] = {threshold, batch_size, fluid_name} -- fluid_name is REQUIRED for fluid drops +-- ["Osmium Dust"] = {nil, 64} -- regular item without threshold +-- ["drop of Molten SpaceTime"] = {1000000, 1, "spacetime"} -- fluid drop with threshold and fluid name cfg["items"] = { - ["drop of Molten SpaceTime"] = {nil, 1}, - ["drop of Molten White Dwarf Matter"] = {nil, 1} + ["drop of Molten SpaceTime"] = {nil, 1, "spacetime"}, + ["drop of Molten White Dwarf Matter"] = {nil, 1, "white_dwarf_matter"} +} + +-- Native fluid maintenance (GTNH 2.9+ only -- requires the StackApi-aware +-- ME interface). Safe to omit entirely on older versions. +-- +-- [fluid_label] = {threshold_mb, batch_mb[, fluid_registry_name]} +-- The third value is an optional override -- the fluid registry name is +-- auto-detected from the craftable's stack, so usually you only need the first two. +-- Pass it explicitly only if auto-detection picks the wrong fluid. +cfg["fluids"] = { + -- ["Molten SpaceTime"] = {nil, 1000}, } cfg["sleep"] = 10 -return cfg +return cfg \ No newline at end of file diff --git a/installer.lua b/installer.lua index 8201509..e870c5a 100644 --- a/installer.lua +++ b/installer.lua @@ -8,7 +8,7 @@ local function exists(filename) return filesystem.exists(shell.getWorkingDirectory() .. "/" .. filename) end -local repo = "https://raw.githubusercontent.com/Niels1006/Infinite-Maintainer/"; +local repo = "https://raw.githubusercontent.com/Echoloquate/Level-Maintainer/"; local branch = "master" for i = 1, #paths do diff --git a/src/AE2.lua b/src/AE2.lua index 6da8b5a..652e012 100644 --- a/src/AE2.lua +++ b/src/AE2.lua @@ -3,23 +3,72 @@ local ME = component.me_interface local AE2 = {} -function AE2.requestItem(name, threshold, count) - craftables = ME.getCraftables({ - ["label"] = name - }) +-- Lightweight cache for specific items only. +-- Values: a craftable userdata (hit), or `false` (negative lookup). +local itemCache = {} +local fluidNameCache = {} -- name -> fluid registry name, or false if the craftable has no fluid stack +local cacheTimestamp = 0 +local CACHE_DURATION = 600 -- 10 minutes in seconds +-- Function to get or cache a specific craftable item +local function getCraftableForItem(itemName) + local currentTime = os.time() + + local cached = itemCache[itemName] + if cached ~= nil and currentTime - cacheTimestamp < CACHE_DURATION then + if cached == false then return nil end + return cached + end + + -- If cache is too old, clear it completely to save memory + if currentTime - cacheTimestamp >= CACHE_DURATION then + itemCache = {} + fluidNameCache = {} + cacheTimestamp = currentTime + end + + -- Look for this specific item in craftables + local craftables = ME.getCraftables({["label"] = itemName}) if #craftables >= 1 then - item = craftables[1].getItemStack() + itemCache[itemName] = craftables[1] -- Cache only this one item + return craftables[1] + end + + itemCache[itemName] = false -- Cache the negative lookup so misspelled entries don't re-query every cycle + return nil +end + +function AE2.requestItem(name, threshold, count, fluidName) + local craftable = getCraftableForItem(name) + + if craftable then + local item = (craftable.getStack or craftable.getItemStack)(craftable) if threshold ~= nil then - itemInSystem = ME.getItemsInNetwork({ - ["label"] = name - }) - if (#itemInSystem > 0 and itemInSystem[1]["size"] > threshold) then - return table.unpack({false, "The amount of " .. itemInSystem[1]["label"] .. " exceeds threshold! Aborting request."}) + local itemInSystem = nil + + if fluidName then + local fluidTag = '{Fluid:' .. fluidName .. '}' + itemInSystem = ME.getItemInNetwork("ae2fc:fluid_drop", 0, fluidTag) + else + if item.name then + if item.tag then + itemInSystem = ME.getItemInNetwork(item.name, item.damage or 0, item.tag) + end + + -- Fallback: try with just the internal name and damage + if itemInSystem == nil then + itemInSystem = ME.getItemInNetwork(item.name, item.damage or 0) + end + end + end + + if itemInSystem ~= nil and itemInSystem.size >= threshold then + return table.unpack({false, "The amount of " .. (itemInSystem.label or name) .. " (" .. itemInSystem.size .. ") meets or exceeds threshold (" .. threshold .. ")! Aborting request."}) end end + if item.label == name then - local craft = craftables[1].request(count) + local craft = craftable.request(count) while craft.isComputing() == true do os.sleep(1) @@ -29,13 +78,53 @@ function AE2.requestItem(name, threshold, count) else return table.unpack({true, "Requested " .. name .. " x " .. count}) end + end + end + return table.unpack({false, name .. " is not craftable!"}) +end + +-- Native fluid maintenance via getFluidInNetwork (GTNH 2.9+). +-- `name` is the fluid craftable label; `fluidName` is the fluid registry name and is +-- auto-detected from the craftable's stack if omitted (pass it only as an override). +function AE2.requestFluid(name, threshold, count, fluidName) + local craftable = getCraftableForItem(name) + + if craftable then + if threshold ~= nil then + if not fluidName then + local cached = fluidNameCache[name] + if cached == nil then + local stack = (craftable.getStack or craftable.getItemStack)(craftable) + cached = (stack and stack.name) or false + fluidNameCache[name] = cached + end + if cached then fluidName = cached end + end + + if fluidName then + local fluidInSystem = ME.getFluidInNetwork(fluidName) + local amount = fluidInSystem and (fluidInSystem.size or fluidInSystem.amount) + if amount and amount >= threshold then + return table.unpack({false, "The amount of " .. (fluidInSystem.label or name) .. " (" .. amount .. " mB) meets or exceeds threshold (" .. threshold .. " mB)! Aborting request."}) + end + end + end + + local craft = craftable.request(count) + while craft.isComputing() == true do + os.sleep(1) + end + if craft.hasFailed() then + return table.unpack({false, "Failed to request " .. name .. " x " .. count .. " mB"}) + else + return table.unpack({true, "Requested " .. name .. " x " .. count .. " mB"}) end end return table.unpack({false, name .. " is not craftable!"}) end -function AE2.checkIfCrafting() +function AE2.checkIfCrafting() local cpus = ME.getCpus() local items = {} for k, v in pairs(cpus) do @@ -48,4 +137,16 @@ function AE2.checkIfCrafting() return items end -return AE2 +-- Returns true if the ME interface exposes the GTNH 2.9+ native fluid API. +function AE2.hasFluidSupport() + return ME.getFluidInNetwork ~= nil +end + +-- Function to manually clear the cache if needed +function AE2.clearCache() + itemCache = {} + fluidNameCache = {} + cacheTimestamp = 0 +end + +return AE2 \ No newline at end of file diff --git a/src/Utility.lua b/src/Utility.lua index 001a214..f19d2bd 100644 --- a/src/Utility.lua +++ b/src/Utility.lua @@ -13,7 +13,6 @@ function dump(o, depth) else return tostring(o) end - end function parser(string)