Enhance peripheral handling: implement caching for peripheral wraps to improve performance
This commit is contained in:
@@ -749,6 +749,28 @@ local function invalidatePeripheralCaches()
|
||||
cachedFurnaces = nil
|
||||
end
|
||||
|
||||
-- Peripheral handle cache (avoids re-creating proxy tables on every call)
|
||||
-- Handles are cleared on peripheral_detach events and during full scans.
|
||||
local wrapCache = {}
|
||||
|
||||
local function wrapCached(name)
|
||||
local handle = wrapCache[name]
|
||||
if handle then return handle end
|
||||
handle = peripheral.wrap(name)
|
||||
if handle then
|
||||
wrapCache[name] = handle
|
||||
end
|
||||
return handle
|
||||
end
|
||||
|
||||
local function invalidateWrapCache(name)
|
||||
if name then
|
||||
wrapCache[name] = nil
|
||||
else
|
||||
wrapCache = {}
|
||||
end
|
||||
end
|
||||
|
||||
local function getChests()
|
||||
local now = os.clock()
|
||||
if cachedChests and (now - cachedChestsTime) < PERIPHERAL_CACHE_TTL then
|
||||
@@ -787,7 +809,7 @@ local function refreshFurnaceStatus()
|
||||
local furnaces = getFurnaces()
|
||||
local status = {}
|
||||
for _, fname in ipairs(furnaces) do
|
||||
local furnace = peripheral.wrap(fname)
|
||||
local furnace = wrapCached(fname)
|
||||
if furnace then
|
||||
local contents = furnace.list()
|
||||
local entry = {
|
||||
@@ -805,7 +827,7 @@ local function refreshFurnaceStatus()
|
||||
end
|
||||
|
||||
local function scanInventory(deviceName)
|
||||
local inv = peripheral.wrap(deviceName)
|
||||
local inv = wrapCached(deviceName)
|
||||
if not inv then return {} end
|
||||
local result = {}
|
||||
for slot, item in pairs(inv.list()) do
|
||||
@@ -823,6 +845,9 @@ end
|
||||
local function refreshCache(onProgress)
|
||||
activity.scanning = true
|
||||
|
||||
-- Clear handle cache so we pick up any changes
|
||||
invalidateWrapCache()
|
||||
|
||||
-- Single pass over peripherals: classify into chests and furnaces
|
||||
local chests = {}
|
||||
local furnaces = {}
|
||||
@@ -851,7 +876,7 @@ local function refreshCache(onProgress)
|
||||
|
||||
for ci, chest in ipairs(chests) do
|
||||
if onProgress then onProgress(ci, #chests, chest) end
|
||||
local inv = peripheral.wrap(chest)
|
||||
local inv = wrapCached(chest)
|
||||
if inv then
|
||||
totalSlots = totalSlots + inv.size()
|
||||
local contents = inv.list()
|
||||
@@ -896,8 +921,8 @@ local function refreshCache(onProgress)
|
||||
cache.usedSlots = usedSlots
|
||||
cache.freeSlots = totalSlots - usedSlots
|
||||
cache.usedRatio = totalSlots > 0 and (usedSlots / totalSlots) or 0
|
||||
cache.dropperOk = peripheral.wrap(DROPPER_NAME) ~= nil
|
||||
cache.barrelOk = peripheral.wrap(BARREL_NAME) ~= nil
|
||||
cache.dropperOk = peripheral.isPresent(DROPPER_NAME)
|
||||
cache.barrelOk = peripheral.isPresent(BARREL_NAME)
|
||||
|
||||
-- Discover all droppers on the network (for location-based dispensing)
|
||||
-- Use name-based matching as peripheral.getType() may return "inventory"
|
||||
@@ -1641,7 +1666,7 @@ local function craftItem(recipeIdx)
|
||||
|
||||
if cache.catalogue[itemName] then
|
||||
for _, source in ipairs(cache.catalogue[itemName]) do
|
||||
local chest = peripheral.wrap(source.chest)
|
||||
local chest = wrapCached(source.chest)
|
||||
if chest then
|
||||
for slot, slotItem in pairs(chest.list()) do
|
||||
local key = source.chest .. ":" .. slot
|
||||
@@ -1737,7 +1762,7 @@ local function craftItem(recipeIdx)
|
||||
for _, r in ipairs(result.results) do
|
||||
-- Find which chest likely received it
|
||||
for _, ch in ipairs(chests) do
|
||||
local chest = peripheral.wrap(ch)
|
||||
local chest = wrapCached(ch)
|
||||
if chest then
|
||||
for slot, slotItem in pairs(chest.list()) do
|
||||
if slotItem.name == r.name then
|
||||
@@ -2060,7 +2085,7 @@ local function drawSmelterDashboard()
|
||||
-- ===== Available Crafting Recipes =====
|
||||
|
||||
-- Turtle status on tab row
|
||||
local turtleOk = craftTurtleName and peripheral.wrap(craftTurtleName) ~= nil
|
||||
local turtleOk = craftTurtleName and peripheral.isPresent(craftTurtleName)
|
||||
local tLabel = turtleOk and " Turtle OK " or " No Turtle "
|
||||
local tBg = turtleOk and colors.lime or colors.red
|
||||
local tFg = turtleOk and colors.black or colors.white
|
||||
@@ -2272,7 +2297,7 @@ end
|
||||
|
||||
local function sortBarrel(barrelOverride)
|
||||
local barrelTarget = (barrelOverride and barrelOverride ~= "") and barrelOverride or BARREL_NAME
|
||||
local barrel = peripheral.wrap(barrelTarget)
|
||||
local barrel = wrapCached(barrelTarget)
|
||||
if not barrel then return end
|
||||
|
||||
local contents = barrel.list()
|
||||
@@ -2344,7 +2369,7 @@ local function autoSmelt()
|
||||
local emptyInputFurnaces = {} -- collected during steps 1-3, filled in step 5
|
||||
|
||||
for _, fname in ipairs(furnaces) do
|
||||
local furnace = peripheral.wrap(fname)
|
||||
local furnace = wrapCached(fname)
|
||||
if furnace then
|
||||
local contents = furnace.list()
|
||||
|
||||
@@ -2420,7 +2445,7 @@ local function autoSmelt()
|
||||
for _, fuel in ipairs(FUEL_LIST) do
|
||||
if catalogue[fuel.name] then
|
||||
for _, source in ipairs(catalogue[fuel.name]) do
|
||||
local chest = peripheral.wrap(source.chest)
|
||||
local chest = wrapCached(source.chest)
|
||||
if chest then
|
||||
for slot, slotItem in pairs(chest.list()) do
|
||||
if slotItem.name == fuel.name then
|
||||
@@ -2505,7 +2530,7 @@ local function autoSmelt()
|
||||
local loaded = false
|
||||
|
||||
for _, source in ipairs(catalogue[itemName]) do
|
||||
local chest = peripheral.wrap(source.chest)
|
||||
local chest = wrapCached(source.chest)
|
||||
if chest then
|
||||
for slot, slotItem in pairs(chest.list()) do
|
||||
if slotItem.name == itemName then
|
||||
@@ -2556,7 +2581,7 @@ local function defragInventory()
|
||||
-- Build a map: itemName -> list of { chest, slot, count, maxCount }
|
||||
local itemSlots = {}
|
||||
for _, chestName in ipairs(chests) do
|
||||
local inv = peripheral.wrap(chestName)
|
||||
local inv = wrapCached(chestName)
|
||||
if inv then
|
||||
local contents = inv.list()
|
||||
local detail_cache = {}
|
||||
@@ -2603,7 +2628,7 @@ local function defragInventory()
|
||||
else
|
||||
local space = recv.max - recv.count
|
||||
local toMove = math.min(donor.count, space)
|
||||
local donorInv = peripheral.wrap(donor.chest)
|
||||
local donorInv = wrapCached(donor.chest)
|
||||
if donorInv then
|
||||
local n = donorInv.pushItems(recv.chest, donor.slot, toMove, recv.slot)
|
||||
if n and n > 0 then
|
||||
@@ -2636,7 +2661,7 @@ local function autoCompost()
|
||||
local didWork = false
|
||||
|
||||
-- 1) Pull bone meal from hopper back to chests
|
||||
local hopper = peripheral.wrap(COMPOST_HOPPER)
|
||||
local hopper = wrapCached(COMPOST_HOPPER)
|
||||
if hopper then
|
||||
local contents = hopper.list()
|
||||
if contents then
|
||||
@@ -2655,7 +2680,7 @@ local function autoCompost()
|
||||
end
|
||||
|
||||
-- 2) Feed compostable items into dropper
|
||||
local dropper = peripheral.wrap(COMPOST_DROPPER)
|
||||
local dropper = wrapCached(COMPOST_DROPPER)
|
||||
if not dropper then return didWork end
|
||||
|
||||
-- Check how much item capacity the dropper has (slots * 64 - current items)
|
||||
@@ -2689,7 +2714,7 @@ local function autoCompost()
|
||||
local toFeed = math.min(available, dropperFreeItems)
|
||||
local fed = 0
|
||||
for _, source in ipairs(catalogue[itemName]) do
|
||||
local chest = peripheral.wrap(source.chest)
|
||||
local chest = wrapCached(source.chest)
|
||||
if chest then
|
||||
for slot, slotItem in pairs(chest.list()) do
|
||||
if slotItem.name == itemName then
|
||||
@@ -2766,7 +2791,7 @@ local function orderItem(itemName, amount, dropperOverride)
|
||||
return false
|
||||
end
|
||||
|
||||
local dropper = peripheral.wrap(dropperTarget)
|
||||
local dropper = wrapCached(dropperTarget)
|
||||
if not dropper then
|
||||
statusMessage = "Dropper offline: " .. dropperTarget
|
||||
statusColor = colors.red
|
||||
@@ -2778,7 +2803,7 @@ local function orderItem(itemName, amount, dropperOverride)
|
||||
|
||||
local remaining = amount
|
||||
for _, entry in ipairs(catalogue[itemName]) do
|
||||
local chest = peripheral.wrap(entry.chest)
|
||||
local chest = wrapCached(entry.chest)
|
||||
if chest then
|
||||
for slot, slotItem in pairs(chest.list()) do
|
||||
if slotItem.name == itemName then
|
||||
@@ -3011,7 +3036,7 @@ local function broadcastState()
|
||||
disabledRecipes = disabledRecipes,
|
||||
smeltable = SMELTABLE,
|
||||
craftable = CRAFTABLE,
|
||||
craftTurtleOk = craftTurtleName and peripheral.wrap(craftTurtleName) ~= nil,
|
||||
craftTurtleOk = craftTurtleName and peripheral.isPresent(craftTurtleName),
|
||||
}
|
||||
networkModem.transmit(BROADCAST_CHANNEL, ORDER_CHANNEL, state)
|
||||
end
|
||||
@@ -3026,13 +3051,13 @@ local function main()
|
||||
print("=================================")
|
||||
print("")
|
||||
|
||||
if peripheral.wrap(DROPPER_NAME) then
|
||||
if peripheral.isPresent(DROPPER_NAME) then
|
||||
print("[OK] Dropper: " .. DROPPER_NAME)
|
||||
else
|
||||
print("[WARN] Dropper not found: " .. DROPPER_NAME)
|
||||
end
|
||||
|
||||
if peripheral.wrap(BARREL_NAME) then
|
||||
if peripheral.isPresent(BARREL_NAME) then
|
||||
print("[OK] Barrel: " .. BARREL_NAME)
|
||||
else
|
||||
print("[WARN] Barrel not found: " .. BARREL_NAME)
|
||||
@@ -3093,12 +3118,12 @@ local function main()
|
||||
print(string.format("[INIT] %d/%d recipes enabled", enabledCount, totalRecipeCount))
|
||||
|
||||
-- Detect compost peripherals
|
||||
if peripheral.wrap(COMPOST_DROPPER) then
|
||||
if peripheral.isPresent(COMPOST_DROPPER) then
|
||||
print("[OK] Compost dropper: " .. COMPOST_DROPPER)
|
||||
else
|
||||
print("[WARN] Compost dropper not found: " .. COMPOST_DROPPER)
|
||||
end
|
||||
if peripheral.wrap(COMPOST_HOPPER) then
|
||||
if peripheral.isPresent(COMPOST_HOPPER) then
|
||||
print("[OK] Compost hopper: " .. COMPOST_HOPPER)
|
||||
else
|
||||
print("[WARN] Compost hopper not found: " .. COMPOST_HOPPER)
|
||||
|
||||
Reference in New Issue
Block a user