180 lines
3.6 KiB
Lua
180 lines
3.6 KiB
Lua
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 |