Implement storage slot defragmentation
This commit is contained in:
parent
c9ac64d6c5
commit
3dabc55825
1
item.lua
1
item.lua
@ -4,7 +4,6 @@ local item = {}
|
|||||||
|
|
||||||
local metatable = {
|
local metatable = {
|
||||||
__eq = util.deepEqual,
|
__eq = util.deepEqual,
|
||||||
__metatable = nil,
|
|
||||||
__tostring = function(ser)
|
__tostring = function(ser)
|
||||||
return textutils.serialise(ser, { compact = true })
|
return textutils.serialise(ser, { compact = true })
|
||||||
end
|
end
|
||||||
|
@ -30,7 +30,6 @@ local metatable = {
|
|||||||
a.count == b.count and
|
a.count == b.count and
|
||||||
a.itemLimit == b.itemLimit
|
a.itemLimit == b.itemLimit
|
||||||
end,
|
end,
|
||||||
__metatable = nil,
|
|
||||||
__index = prototype,
|
__index = prototype,
|
||||||
__tostring = function(ser)
|
__tostring = function(ser)
|
||||||
return textutils.serialise({
|
return textutils.serialise({
|
||||||
|
@ -87,9 +87,12 @@ function prototype:moveItemsTo(count, fromSlot, otherChest, toSlot)
|
|||||||
return tx
|
return tx
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function prototype:getIdentifier()
|
||||||
|
return peripheral.getName(self.peripheral)
|
||||||
|
end
|
||||||
|
|
||||||
local metatable = {
|
local metatable = {
|
||||||
__index = prototype,
|
__index = prototype,
|
||||||
__metatable = nil,
|
|
||||||
__tostring = function(ser)
|
__tostring = function(ser)
|
||||||
local slots = {}
|
local slots = {}
|
||||||
for key,value in pairs(ser.slots) do
|
for key,value in pairs(ser.slots) do
|
||||||
|
117
stackgroup.lua
Normal file
117
stackgroup.lua
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
local util = require("util")
|
||||||
|
|
||||||
|
local stackgroup = {}
|
||||||
|
local prototype = {}
|
||||||
|
local metatable = {}
|
||||||
|
|
||||||
|
function prototype:defragment(chests)
|
||||||
|
table.sort(self, function(a, b) return a.count < b.count end)
|
||||||
|
|
||||||
|
local resultGroup = {
|
||||||
|
item = self.item,
|
||||||
|
total = self.total
|
||||||
|
}
|
||||||
|
|
||||||
|
setmetatable(resultGroup, metatable)
|
||||||
|
|
||||||
|
local top = #self
|
||||||
|
local bottom = 1
|
||||||
|
|
||||||
|
-- Find largest non-full stack
|
||||||
|
for i=top,bottom,-1 do
|
||||||
|
local entry = self[i]
|
||||||
|
if entry:getStack(chests).availableCount() ~= 0 then
|
||||||
|
top = i
|
||||||
|
break
|
||||||
|
else
|
||||||
|
resultGroup[#resultGroup + 1] = entry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
while top > bottom do
|
||||||
|
local topEntry = self[top]
|
||||||
|
local bottomEntry = self[bottom]
|
||||||
|
|
||||||
|
local txCap = math.min(bottomEntry.count, topEntry:getStack(chests).availableCount())
|
||||||
|
local tx = bottomEntry:getChest(chests):moveItemsTo(txCap, bottomEntry.slot, topEntry:getChest(chests), topEntry.slot)
|
||||||
|
|
||||||
|
if tx ~= txCap then
|
||||||
|
error("Safe inventory transfer failed unexpectedly: "..textutils.serialise({
|
||||||
|
from = { chest = bottomEntry:getChest(chests):getIdentifier(), slot = bottomEntry.slot },
|
||||||
|
to = { chest = topEntry:getChest(chests):getIdentifier(), slot = topEntry.slot },
|
||||||
|
txExpected = txCap,
|
||||||
|
txActual = tx
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
|
||||||
|
bottomEntry.count = bottomEntry.count - tx
|
||||||
|
topEntry.count = topEntry.count + tx
|
||||||
|
|
||||||
|
if bottomEntry.count == 0 then
|
||||||
|
bottom = bottom + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if topEntry:getStack(chests).availableCount() == 0 then
|
||||||
|
top = top - 1
|
||||||
|
resultGroup[#resultGroup + 1] = topEntry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if top == bottom and self[top].count > 0 then
|
||||||
|
resultGroup[#resultGroup+1] = self[top]
|
||||||
|
end
|
||||||
|
|
||||||
|
return resultGroup
|
||||||
|
end
|
||||||
|
|
||||||
|
metatable.__index = prototype
|
||||||
|
|
||||||
|
local groupEntryPrototype = {}
|
||||||
|
|
||||||
|
function groupEntryPrototype:getStack(chests)
|
||||||
|
return self:getChest(chests).slots[self.slot]
|
||||||
|
end
|
||||||
|
|
||||||
|
function groupEntryPrototype:getChest(chests)
|
||||||
|
return chests[self.chestIndex]
|
||||||
|
end
|
||||||
|
|
||||||
|
local groupEntryMetatable = {
|
||||||
|
__index = groupEntryPrototype
|
||||||
|
}
|
||||||
|
|
||||||
|
function stackgroup.fromChests(...)
|
||||||
|
local chests = { ... }
|
||||||
|
local groups = {}
|
||||||
|
local outGroups = {}
|
||||||
|
|
||||||
|
for chestIndex,chest in ipairs(chests) do
|
||||||
|
for slotKey,slot in pairs(chest.slots) do
|
||||||
|
local group = util.find(groups, function(value) return value.item == slot.item end)
|
||||||
|
if group == nil then
|
||||||
|
group = {
|
||||||
|
item = slot.item,
|
||||||
|
total = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
setmetatable(group, metatable)
|
||||||
|
|
||||||
|
groups[#groups + 1] = group
|
||||||
|
end
|
||||||
|
|
||||||
|
local entry = {
|
||||||
|
chestIndex = chestIndex,
|
||||||
|
slot = slotKey,
|
||||||
|
count = slot.count
|
||||||
|
}
|
||||||
|
setmetatable(entry, groupEntryMetatable)
|
||||||
|
|
||||||
|
group[#group + 1] = entry
|
||||||
|
group.total = group.total + slot.count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return outGroups
|
||||||
|
end
|
||||||
|
|
||||||
|
return stackgroup
|
Loading…
x
Reference in New Issue
Block a user