From 8328e9bafc10b8cd56d22c858ce503445b827dd6 Mon Sep 17 00:00:00 2001 From: Echoloquate Date: Thu, 14 Aug 2025 11:02:24 -0700 Subject: [PATCH 1/8] Updated to use new 2.8 functions --- installer.lua | 2 +- src/AE2.lua | 61 +++++++++++++++++++++++++++++++++++++------------ src/Utility.lua | 1 - 3 files changed, 48 insertions(+), 16 deletions(-) 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..34d1273 100644 --- a/src/AE2.lua +++ b/src/AE2.lua @@ -3,23 +3,51 @@ local ME = component.me_interface local AE2 = {} +-- Cache for craftables with timestamp +local craftablesCache = {} +local cacheTimestamp = 0 +local CACHE_DURATION = 600 -- 10 minutes in seconds + +-- Function to get cached craftables or refresh if needed +local function getCachedCraftables() + local currentTime = os.time() + + -- Check if cache is still valid (within 10 minutes) + if currentTime - cacheTimestamp < CACHE_DURATION and next(craftablesCache) ~= nil then + return craftablesCache + end + + -- Cache is expired or empty, refresh it + local allCraftables = ME.getCraftables() + craftablesCache = {} + + -- Index craftables by label for faster lookup + for _, craftable in pairs(allCraftables) do + local itemStack = craftable.getItemStack() + if itemStack and itemStack.label then + craftablesCache[itemStack.label] = craftable + end + end + + cacheTimestamp = currentTime + return craftablesCache +end + function AE2.requestItem(name, threshold, count) - craftables = ME.getCraftables({ - ["label"] = name - }) + local cachedCraftables = getCachedCraftables() + local craftable = cachedCraftables[name] - if #craftables >= 1 then - item = craftables[1].getItemStack() + if craftable then + local item = craftable.getItemStack() 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 = ME.getItemInNetwork(name) + if itemInSystem ~= nil and itemInSystem.size > threshold then + return table.unpack({false, "The amount of " .. itemInSystem.label .. " exceeds 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 +57,12 @@ 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 -function AE2.checkIfCrafting() +function AE2.checkIfCrafting() local cpus = ME.getCpus() local items = {} for k, v in pairs(cpus) do @@ -48,4 +75,10 @@ function AE2.checkIfCrafting() return items end -return AE2 +-- Function to manually clear the cache if needed +function AE2.clearCache() + craftablesCache = {} + 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) From 87c9d33653f14518d84504ec5ceb6f82ec1ca609 Mon Sep 17 00:00:00 2001 From: Echoloquate Date: Thu, 14 Aug 2025 11:03:51 -0700 Subject: [PATCH 2/8] Readme update --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1e45f52..be98883 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,31 @@ # 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 !!** From 85b541baffe98ba24899a624a4f0392c119203d0 Mon Sep 17 00:00:00 2001 From: Echoloquate Date: Thu, 14 Aug 2025 11:39:43 -0700 Subject: [PATCH 3/8] Tweaked output --- Maintainer.lua | 5 +++-- src/AE2.lua | 43 ++++++++++++++++++++++--------------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/Maintainer.lua b/Maintainer.lua index 5a78c47..b086e04 100644 --- a/Maintainer.lua +++ b/Maintainer.lua @@ -9,11 +9,12 @@ while true do local itemsCrafting = ae2.checkIfCrafting() for item, config in pairs(items) do - if itemsCrafting[item] ~= true then + if itemsCrafting[item] == true then + logInfo(item .. " is already being crafted, skipping...") + else local success, answer = ae2.requestItem(item, config[1], config[2]) logInfo(answer) end - end os.sleep(sleepInterval) end diff --git a/src/AE2.lua b/src/AE2.lua index 34d1273..76e0369 100644 --- a/src/AE2.lua +++ b/src/AE2.lua @@ -3,43 +3,44 @@ local ME = component.me_interface local AE2 = {} --- Cache for craftables with timestamp -local craftablesCache = {} +-- Lightweight cache for specific items only +local itemCache = {} local cacheTimestamp = 0 local CACHE_DURATION = 600 -- 10 minutes in seconds --- Function to get cached craftables or refresh if needed -local function getCachedCraftables() +-- Function to get or cache a specific craftable item +local function getCraftableForItem(itemName) local currentTime = os.time() - -- Check if cache is still valid (within 10 minutes) - if currentTime - cacheTimestamp < CACHE_DURATION and next(craftablesCache) ~= nil then - return craftablesCache + -- Check if we have a cached version of this specific item and it's still valid + if itemCache[itemName] and currentTime - cacheTimestamp < CACHE_DURATION then + return itemCache[itemName] end - -- Cache is expired or empty, refresh it - local allCraftables = ME.getCraftables() - craftablesCache = {} + -- If cache is too old, clear it completely to save memory + if currentTime - cacheTimestamp >= CACHE_DURATION then + itemCache = {} + cacheTimestamp = currentTime + end - -- Index craftables by label for faster lookup - for _, craftable in pairs(allCraftables) do - local itemStack = craftable.getItemStack() - if itemStack and itemStack.label then - craftablesCache[itemStack.label] = craftable - end + -- Look for this specific item in craftables + local craftables = ME.getCraftables({["label"] = itemName}) + if #craftables >= 1 then + itemCache[itemName] = craftables[1] -- Cache only this one item + return craftables[1] end - cacheTimestamp = currentTime - return craftablesCache + itemCache[itemName] = nil -- Cache that it's not craftable + return nil end function AE2.requestItem(name, threshold, count) - local cachedCraftables = getCachedCraftables() - local craftable = cachedCraftables[name] + local craftable = getCraftableForItem(name) if craftable then local item = craftable.getItemStack() if threshold ~= nil then + -- Use the newer getItemInNetwork function local itemInSystem = ME.getItemInNetwork(name) if itemInSystem ~= nil and itemInSystem.size > threshold then return table.unpack({false, "The amount of " .. itemInSystem.label .. " exceeds threshold! Aborting request."}) @@ -77,7 +78,7 @@ end -- Function to manually clear the cache if needed function AE2.clearCache() - craftablesCache = {} + itemCache = {} cacheTimestamp = 0 end From ddc2cc81f03a7b88751b049eb3494c3172fea34c Mon Sep 17 00:00:00 2001 From: Echoloquate Date: Thu, 14 Aug 2025 12:48:18 -0700 Subject: [PATCH 4/8] Added nbt handling for fluid drops --- Maintainer.lua | 5 +++-- config.lua | 12 ++++++------ src/AE2.lua | 26 +++++++++++++++++++++----- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Maintainer.lua b/Maintainer.lua index b086e04..0ce14d3 100644 --- a/Maintainer.lua +++ b/Maintainer.lua @@ -12,9 +12,10 @@ while true do if itemsCrafting[item] == true then logInfo(item .. " is already being crafted, skipping...") else - local success, answer = ae2.requestItem(item, config[1], config[2]) + local success, answer = ae2.requestItem(item, config[1], config[2], config[3]) logInfo(answer) end + end os.sleep(sleepInterval) -end +end \ No newline at end of file diff --git a/config.lua b/config.lua index 42d8b31..87da6de 100644 --- a/config.lua +++ b/config.lua @@ -2,15 +2,15 @@ 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"} } cfg["sleep"] = 10 -return cfg +return cfg \ No newline at end of file diff --git a/src/AE2.lua b/src/AE2.lua index 76e0369..122744c 100644 --- a/src/AE2.lua +++ b/src/AE2.lua @@ -34,16 +34,32 @@ local function getCraftableForItem(itemName) return nil end -function AE2.requestItem(name, threshold, count) +function AE2.requestItem(name, threshold, count, fluidName) local craftable = getCraftableForItem(name) if craftable then local item = craftable.getItemStack() if threshold ~= nil then - -- Use the newer getItemInNetwork function - local itemInSystem = ME.getItemInNetwork(name) - if itemInSystem ~= nil and itemInSystem.size > threshold then - return table.unpack({false, "The amount of " .. itemInSystem.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 From 2a5951b64ed85d30bc90e949ebdab6af2f5513f4 Mon Sep 17 00:00:00 2001 From: Echoloquate Date: Sat, 16 May 2026 15:05:48 -0700 Subject: [PATCH 5/8] Fix getItemStack rename for GTNH 2.9 / OC StackApi --- src/AE2.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AE2.lua b/src/AE2.lua index 122744c..49bcae2 100644 --- a/src/AE2.lua +++ b/src/AE2.lua @@ -38,7 +38,7 @@ function AE2.requestItem(name, threshold, count, fluidName) local craftable = getCraftableForItem(name) if craftable then - local item = craftable.getItemStack() + local item = (craftable.getStack or craftable.getItemStack)(craftable) if threshold ~= nil then local itemInSystem = nil From a4fc389c47737d9c42e30de8f52090a261a0a9cf Mon Sep 17 00:00:00 2001 From: Echoloquate Date: Sat, 16 May 2026 15:12:12 -0700 Subject: [PATCH 6/8] Add native fluid maintenance for GTNH 2.9 via getFluidInNetwork --- Maintainer.lua | 19 ++++++++++++++++--- README.md | 27 +++++++++++++++++++++++++-- config.lua | 11 +++++++++++ src/AE2.lua | 28 ++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 5 deletions(-) diff --git a/Maintainer.lua b/Maintainer.lua index 0ce14d3..f6d65e6 100644 --- a/Maintainer.lua +++ b/Maintainer.lua @@ -3,11 +3,12 @@ local cfg = require("config") local util = require("src.Utility") local items = cfg.items +local fluids = cfg.fluids local sleepInterval = cfg.sleep - + while true do local itemsCrafting = ae2.checkIfCrafting() - + for item, config in pairs(items) do if itemsCrafting[item] == true then logInfo(item .. " is already being crafted, skipping...") @@ -15,7 +16,19 @@ while true do 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 \ No newline at end of file diff --git a/README.md b/README.md index be98883..f1dbed5 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,31 @@ 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. +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+. -**!! Keep in mind that threshold should only be added if necessary and preferrably not in mainnet, since it has a performance impact !!** +## 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, "spacetime"}, +} +``` + +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 registry name is the internal id (e.g. `spacetime`, `white_dwarf_matter`). 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 87da6de..9845249 100644 --- a/config.lua +++ b/config.lua @@ -11,6 +11,17 @@ cfg["items"] = { ["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} +-- ["Molten SpaceTime"] = {1000000, 1000, "spacetime"} +-- fluid_label must match the fluid's display name as shown in the AE crafting terminal. +-- fluid_registry_name is the internal name (same as the 3rd arg used in cfg.items above). +cfg["fluids"] = { + -- ["Molten SpaceTime"] = {nil, 1000, "spacetime"}, +} + cfg["sleep"] = 10 return cfg \ No newline at end of file diff --git a/src/AE2.lua b/src/AE2.lua index 49bcae2..01551a2 100644 --- a/src/AE2.lua +++ b/src/AE2.lua @@ -79,6 +79,34 @@ function AE2.requestItem(name, threshold, count, fluidName) 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. +function AE2.requestFluid(name, threshold, count, fluidName) + local craftable = getCraftableForItem(name) + + if craftable then + if threshold ~= nil and 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 + + 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() local cpus = ME.getCpus() local items = {} From f99d6c88357a2b7238e4c06e9af1f98c954bfce4 Mon Sep 17 00:00:00 2001 From: Echoloquate Date: Sat, 16 May 2026 15:40:42 -0700 Subject: [PATCH 7/8] Auto-detect fluid registry name from craftable stack --- README.md | 4 ++-- config.lua | 10 +++++----- src/AE2.lua | 20 ++++++++++++++------ 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f1dbed5..5332149 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,11 @@ GTNH 2.9 unified items and fluids in the OpenComputers AE2 integration, so fluid ```lua cfg["fluids"] = { - ["Molten SpaceTime"] = {1000000, 1000, "spacetime"}, + ["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 registry name is the internal id (e.g. `spacetime`, `white_dwarf_matter`). Omit the block entirely on pre-2.9 setups. +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 !!** diff --git a/config.lua b/config.lua index 9845249..0820bda 100644 --- a/config.lua +++ b/config.lua @@ -14,12 +14,12 @@ cfg["items"] = { -- 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} --- ["Molten SpaceTime"] = {1000000, 1000, "spacetime"} --- fluid_label must match the fluid's display name as shown in the AE crafting terminal. --- fluid_registry_name is the internal name (same as the 3rd arg used in cfg.items above). +-- [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, "spacetime"}, + -- ["Molten SpaceTime"] = {nil, 1000}, } cfg["sleep"] = 10 diff --git a/src/AE2.lua b/src/AE2.lua index 01551a2..e987f94 100644 --- a/src/AE2.lua +++ b/src/AE2.lua @@ -80,16 +80,24 @@ function AE2.requestItem(name, threshold, count, fluidName) end -- Native fluid maintenance via getFluidInNetwork (GTNH 2.9+). --- `name` is the fluid craftable label; `fluidName` is the fluid registry name. +-- `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 and 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."}) + if threshold ~= nil then + if not fluidName then + local stack = (craftable.getStack or craftable.getItemStack)(craftable) + fluidName = stack and stack.name + 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 From 1ed30470eca31cdc4805d99aab06468ead81600c Mon Sep 17 00:00:00 2001 From: Echoloquate Date: Sat, 16 May 2026 15:47:03 -0700 Subject: [PATCH 8/8] Cache negative lookups and fluid names, warn on missing 2.9 API --- Maintainer.lua | 5 +++++ src/AE2.lua | 37 ++++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Maintainer.lua b/Maintainer.lua index f6d65e6..78ced9c 100644 --- a/Maintainer.lua +++ b/Maintainer.lua @@ -6,6 +6,11 @@ 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() diff --git a/src/AE2.lua b/src/AE2.lua index e987f94..652e012 100644 --- a/src/AE2.lua +++ b/src/AE2.lua @@ -3,34 +3,38 @@ local ME = component.me_interface local AE2 = {} --- Lightweight cache for specific items only +-- 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() - - -- Check if we have a cached version of this specific item and it's still valid - if itemCache[itemName] and currentTime - cacheTimestamp < CACHE_DURATION then - return itemCache[itemName] + + 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 itemCache[itemName] = craftables[1] -- Cache only this one item return craftables[1] end - - itemCache[itemName] = nil -- Cache that it's not craftable + + itemCache[itemName] = false -- Cache the negative lookup so misspelled entries don't re-query every cycle return nil end @@ -88,8 +92,13 @@ function AE2.requestFluid(name, threshold, count, fluidName) if craftable then if threshold ~= nil then if not fluidName then - local stack = (craftable.getStack or craftable.getItemStack)(craftable) - fluidName = stack and stack.name + 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 @@ -128,9 +137,15 @@ function AE2.checkIfCrafting() return items end +-- 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