local ItemStack = require("storage.itemstack") local Sentinel = require("storage.sentinel") local Chest = Sentinel:tag({}, Sentinel.CHEST) Chest.__index = Chest -- Homogeneity allows chest scan to clone empty itemDetail slot to all empty slots in chest function Chest:fromPeripheral(chest, homogeneous) if type(chest) == "string" then local chestResult = peripheral.wrap(chest) if chestResult == nil then chestResult = peripheral.find(chest) end chest = chestResult end if chest == nil then return nil end local obj = { name = peripheral.getName(chest), chest = chest, size = chest.size(), homogeneous = homogeneous } setmetatable(obj, self) obj.__index = obj obj:rescan() return obj end function Chest:rescan() -- Clear stack data for i=1,self:getSize() do self[i] = nil end self.size = self.chest.size() local emptyStack = nil local listData = self.chest.list() for i=1,self:getSize() do local data = listData[i] local stack if data == nil and self.homogeneous then -- Empty stack if emptyStack == nil then emptyStack = ItemStack:fromDetail(self.chest, self.chest.getItemDetail(i), i) if not emptyStack:isEmpty() then error("Expected empty stack detail, but got populated stack!") end end stack = emptyStack:clone(i) else stack = ItemStack:fromDetail(self.chest, self.chest.getItemDetail(i), i) end self[i] = stack end end function Chest:toSerializable() local ser = { name = self:getName(), size = self:getSize(), homogeneous = self.homogeneous } local skipEmpty = false for i,v in ipairs(self) do local stackSer = v:toSerializable() -- Skip all but the first homogeneous slot if v:isEmpty() then if skipEmpty then goto continue end skipEmpty = self.homogeneous end ser[i] = stackSer ::continue:: end return ser end function Chest:fromSerializable(ser, inv) -- Auto-wrap if inventory is not supplied if inv == nil then inv = peripheral.wrap(ser.name) if inv == nil then return nil end end local obj = { name = ser.name, size = ser.size, homogeneous = ser.homogeneous, chest = inv } local emptyStack = nil for i=1,ser.size do local stackSer = ser[i] local stack if stackSer == nil then if emptyStack == nil then -- Missing inventory slot data! Must get item detail stack = ItemStack:fromDetail(inv, inv.getItemDetail(i), i) else stack = emptyStack:clone(i) end else stack = ItemStack:fromSerializable(stackSer, inv) end if ser.homogeneous and emptyStack == nil and stack:isEmpty() then emptyStack = stackSer end obj[i] = stack end setmetatable(obj, self) obj.__index = obj return obj end function Chest:hasChanged(thorough) local mySize = self:getSize() if mySize ~= self.chest.size() then return true end local listData = self.chest.list() for i=1,mySize do if (listData[i] == nil) ~= (self[i] == nil) then return true end if listData[i] ~= nil and self[i]:hasChanged(listData[i], thorough) then return true end end return false end function Chest:getSize() return self.size end function Chest:getName() return self.name end function Chest:getInventory() return self.chest end function Chest:find(query) local result = {} for i=1,self:getSize() do if self[i]:matches(query) then table.insert(result, self[i]) end end return result end return Chest