local Chest = require("storage.chest") local Sentinel = require("storage.sentinel") local Storage = Sentinel:tag({}, Sentinel.STORAGE) Storage.__index = Storage local function _attach(stor, name, homogeneous) table.insert(stor, Chest:fromPeripheral(name, homogeneous)) end function Storage.assumeHomogeneous(names) local mappings = {} for _,name in ipairs(names) do mappings[name] = true end return mappings end function Storage:fromPeripherals(peripheralDefs) local obj = { count = #peripheralDefs } for name,homogeneous in pairs(peripheralDefs) do _attach(obj, name, homogeneous) end setmetatable(obj, self) obj.__index = obj return obj end function Storage:toSerializable() local ser = { count = self.count } for _,chest in ipairs(self) do table.insert(ser, chest:toSerializable()) end return ser end function Storage:fromSerializable(ser) local obj = { count = ser.count } for _,chestSer in ipairs(ser) do local chest = Chest:fromSerializable(chestSer) if chest ~= nil then table.insert(obj, chest) end end setmetatable(obj, self) obj.__index = self return obj end function Storage:isAttached(name) for index,chest in ipairs(self) do if chest:getName() == name then return true, chest, index end end return false, nil, nil end function Storage:attach(name, homogeneous) if self:isAttached(name) then return end _attach(self, name, homogeneous) end function Storage:attachAll(peripheralDefs) for name,homogeneous in pairs(peripheralDefs) do self:attach(name, homogeneous) end return self end function Storage:detach(name) local attached, _, index = self:isAttached(name) if attached then return table.remove(self, index) end return nil end function Storage:find(query) local result = {} for _,chest in ipairs(self) do for _,stack in ipairs(chest:find(query)) do table.insert(result, stack) end end return result end -- Find all stacks eligible to accept the given query function Storage:findInsertTargets(sourceStack) local result = self:find(function(stack) return sourceStack:canTransfer(stack) end) -- Insertion should prioritize filling populated stacks table.sort(result, function(a, b) return a:getCount() > b:getCount() end) return result end function Storage:findExtractTargets(targetStack) -- Only transfer non-empty stacks local result = self:find(function(stack) return (not stack:isEmpty()) and stack:canTransfer(targetStack) end) -- Extraction should prioritize emptying populated stacks table.sort(result, function(a, b) return a:getCount() < b:getCount() end) return result end function Storage:insertStack(stack) local targets = self:findInsertTargets(stack) for _,target in ipairs(targets) do if stack:isEmpty() then return true end stack:transferTo(target) end return false end return Storage