Implement basic inventory scanning and transfer
This commit is contained in:
commit
33ac91e24b
42
item.lua
Normal file
42
item.lua
Normal file
@ -0,0 +1,42 @@
|
||||
local util = require("util")
|
||||
|
||||
local item = {}
|
||||
|
||||
local metatable = {
|
||||
__eq = util.deepEqual,
|
||||
__metatable = nil,
|
||||
__tostring = function(ser)
|
||||
return textutils.serialise(ser, { compact = true })
|
||||
end
|
||||
}
|
||||
|
||||
function item.fromDetail(detail)
|
||||
local detailItem = {
|
||||
name = detail.name,
|
||||
displayName = detail.displayName,
|
||||
tags = detail.tags,
|
||||
itemGroups = detail.itemGroups,
|
||||
maxCount = detail.maxCount
|
||||
}
|
||||
|
||||
setmetatable(detailItem, metatable)
|
||||
|
||||
return detailItem
|
||||
end
|
||||
|
||||
function item.fromString(str)
|
||||
local strItem = textutils.unserialize(str)
|
||||
if type(strItem.name) ~= "string" or
|
||||
type(strItem.displayName) ~= "string" or
|
||||
type(strItem.tags) ~= "table" or
|
||||
type(strItem.itemGroups) ~= "table" or
|
||||
type(strItem.maxCount) ~= "number" then
|
||||
error("Could not parse item: "..str)
|
||||
end
|
||||
|
||||
setmetatable(strItem, metatable)
|
||||
|
||||
return strItem
|
||||
end
|
||||
|
||||
return item
|
83
itemstack.lua
Normal file
83
itemstack.lua
Normal file
@ -0,0 +1,83 @@
|
||||
local item = require("item")
|
||||
|
||||
local itemstack = {}
|
||||
local prototype = {}
|
||||
|
||||
function prototype:isBlank()
|
||||
return self.item == nil
|
||||
end
|
||||
|
||||
function prototype:availableCount()
|
||||
return self.itemLimit - self.count
|
||||
end
|
||||
|
||||
function prototype:canTransferTo(otherStack)
|
||||
if self:isBlank() or self.item ~= otherStack.item then
|
||||
return 0
|
||||
end
|
||||
|
||||
local availableCount = otherStack:availableCount()
|
||||
if availableCount >= self.count then
|
||||
return self.count
|
||||
end
|
||||
|
||||
return availableCount
|
||||
end
|
||||
|
||||
local metatable = {
|
||||
__eq = function(a, b)
|
||||
return a.item == b.item and
|
||||
a.count == b.count and
|
||||
a.itemLimit == b.itemLimit
|
||||
end,
|
||||
__metatable = nil,
|
||||
__index = prototype,
|
||||
__tostring = function(ser)
|
||||
return textutils.serialise({
|
||||
item = tostring(ser.item),
|
||||
count = ser.count,
|
||||
itemLimit = ser.itemLimit
|
||||
}, { compact = true })
|
||||
end
|
||||
}
|
||||
|
||||
local function newItemStack(itemInst, count, itemLimit)
|
||||
local stack = {
|
||||
item = itemInst,
|
||||
count = count,
|
||||
itemLimit = itemLimit
|
||||
}
|
||||
|
||||
setmetatable(stack, metatable)
|
||||
|
||||
return stack
|
||||
end
|
||||
|
||||
function itemstack.blank(itemLimit)
|
||||
return newItemStack(nil, 0, itemLimit)
|
||||
end
|
||||
|
||||
function itemstack.fromItemDetail(detail, itemLimit)
|
||||
if detail == nil then
|
||||
return itemstack.blank(itemLimit)
|
||||
end
|
||||
|
||||
return newItemStack(item.fromDetail(detail), detail.count, itemLimit)
|
||||
end
|
||||
|
||||
function itemstack.fromString(str)
|
||||
local strStack = textutils.unserialize(str)
|
||||
if type(strStack.item) ~= "string" or
|
||||
type(strStack.count) ~= "number" or
|
||||
type(strStack.itemLimit) ~= "number" then
|
||||
error("Could not parse itemstack: "..str)
|
||||
end
|
||||
|
||||
strStack.item = item.fromString(strStack.item)
|
||||
|
||||
setmetatable(strStack, metatable)
|
||||
|
||||
return strStack
|
||||
end
|
||||
|
||||
return itemstack
|
134
localchest.lua
Normal file
134
localchest.lua
Normal file
@ -0,0 +1,134 @@
|
||||
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(peripheral.getName(otherChest.peripheral), fromSlot, count, toSlot)
|
||||
myStack.count = myStack.count - tx
|
||||
targetStack.count = targetStack.count + tx
|
||||
|
||||
return tx
|
||||
end
|
||||
|
||||
local metatable = {
|
||||
__index = prototype,
|
||||
__metatable = nil,
|
||||
__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)
|
||||
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
|
28
util.lua
Normal file
28
util.lua
Normal file
@ -0,0 +1,28 @@
|
||||
local util = {}
|
||||
|
||||
function util.deepEqual(a, b)
|
||||
local varType = type(a)
|
||||
if varType ~= type(b) then
|
||||
return false
|
||||
end
|
||||
|
||||
if varType == "table" then
|
||||
for key,_ in pairs(b) do
|
||||
if a[key] == nil then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
for key,value in pairs(a) do
|
||||
if not util.deepEqual(value, b[key]) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return a == b
|
||||
end
|
||||
|
||||
return util
|
Loading…
x
Reference in New Issue
Block a user