local itemstack = require("itemstack") local localchest = {} local prototype = {} function prototype:exists() return self.peripheral.size() ~= nil end function prototype:scanSlot(slot) local stack = itemstack.fromItemDetail(self.peripheral.getItemDetail(slot), self.peripheral.getItemLimit(slot)) self.slots[slot] = stack return stack end function prototype:rescan() if not self:exists() then return false end self.slots = {} self.size = self.peripheral.size() for key,_ in pairs(self.peripheral.list()) do self:scanSlot(key) end return true end function prototype:sanityCheck() if not self:exists() then return false end local listData = self.peripheral.list() for key,_ in pairs(self.slots) do if listData[key] == nil then return false end end for key,stackData in pairs(listData) do local cachedStack = self.slots[key] if cachedStack == nil or cachedStack.item.name ~= stackData.name or cachedStack.count ~= stackData.count then return false end end return true end function prototype:getSlot(slot) local stack = self.slots[slot] if stack == nil then return itemstack.blank(self.peripheral.getItemLimit(slot)) end return stack end function prototype:moveItemsTo(count, fromSlot, otherChest, toSlot) if not otherChest:exists() then return 0 end local myStack = self:getSlot(fromSlot) local targetStack = otherChest:getSlot(toSlot) local txCap = myStack:canTransferTo(targetStack) if count > txCap then return 0 end local tx = self.peripheral.pushItems(otherChest:getIdentifier(), fromSlot, count, toSlot) myStack.count = myStack.count - tx if myStack.count == 0 then self.slots[fromSlot] = nil end targetStack.count = targetStack.count + tx if targetStack:isBlank() then targetStack.item = myStack.item otherChest.slots[toSlot] = targetStack end return tx end function prototype:moveItemsToPeripheral(count, fromSlot, target, toSlot) local myStack = self:getSlot(fromSlot) local tx = self.peripheral.pushItems(peripheral.getName(target), fromSlot, count, toSlot) myStack.count = myStack.count - tx if myStack.count == 0 then self.slots[fromSlot] = nil end return tx end function prototype:pullItemsFromPeripheral(count, fromSlot, fromTarget, toSlot) local myStack = self:getSlot(toSlot) local perStack = itemstack.fromItemDetail(fromTarget.getItemDetail(fromSlot), fromTarget.getItemLimit(fromSlot)) if not perStack:canTransferTo(myStack) then error("Cannot pull items from peripheral to chest: "..textutils.serialise({ from = { peripheral = peripheral.getName(fromTarget), slot = fromSlot }, to = { chest = self:getIdentifier(), slot = toSlot }, count = count })) end local tx = fromTarget.pushItems(self:getIdentifier(), fromSlot, count, toSlot) if myStack:isBlank() then myStack.item = perStack.item self[toSlot] = myStack end myStack.count = myStack.count + tx return tx end function prototype:getIdentifier() return peripheral.getName(self.peripheral) end local metatable = { __index = prototype, __tostring = function(ser) local slots = {} for key,value in pairs(ser.slots) do slots[key] = tostring(value) end return textutils.serialise({ peripheral = peripheral.getName(ser.peripheral), slots = slots, size = ser.size }, { compact = true }) end } function localchest.fromPeripheral(per) if type(per) == "string" then per = peripheral.wrap(per) end local chest = { peripheral = per, slots = {}, size = 0 } setmetatable(chest, metatable) return chest end function localchest.fromString(str) local chest = textutils.unserialize(str) if type(chest.peripheral) ~= "string" or type(chest.slots) ~= "table" or type(chest.size) ~= "number" then error("Could not parse localchest: "..str) end local per = peripheral.wrap(chest.peripheral) if per == nil then error("Could not wrap peripheral for chest: "..chest.peripheral) end chest.peripheral = per for key,value in pairs(chest.slots) do chest.slots[key] = itemstack.fromString(value) end setmetatable(chest, metatable) return chest end return localchest