diff --git a/jturtle/inventory.lua b/jturtle/inventory.lua new file mode 100644 index 0000000..dd9fed6 --- /dev/null +++ b/jturtle/inventory.lua @@ -0,0 +1,150 @@ +-- Created by Jef Roosens + +-- Manages the inventory +local Inventory = { + selected = nil, -- Currently selected slot + slots = nil, -- table containing contents of all slots + items = nil, -- table containing items and their slots (fast lookup) + free = nil, -- table containing free slots +} + + +function Inventory:new(o) + o = o or {} + setmetatable(o, self) + self.__index = self + + o.selected = selected or turtle.getSelectedSlot() + + -- Update inventory if no data is provided + -- Empty tables are also truethy + if o.slots == nil or o.items == nil then o:update() end + + return o +end + + +-- Select the given slot if valid +-- +-- @param slot slot to select +function Inventory:select(slot) + -- Exit if needed + if self.selected == slot or slot < 1 or slot > 16 then return end + + turtle.select(slot) + self.selected = slot +end + + +-- Transfer items between slots. +-- +-- @param from slot to transfer from +-- @param to slot to transfer to +-- @param count amount of items to transfer. If count is not specified or count +-- is greater than the possible transfer, the maximum transfer will be done. +-- @return wether all items were transferred +function Inventory:transfer(from, to, count) + -- Exit if from is empty + if not self.slots[from] then return true end + + count = count or self.slots[from].count + local return_value = true + + -- If to isn't empty, check if we can fit it all and if they're the same + -- item type + if self.slots[to] then + -- Exit if it's a differen item type or if there's no space left + if self.slots[to].name ~= self.slots[from].name or + self.slots[to].count == 64 then return false end + + count = math.min(count, 64 - self.slots[to].count) + return_value = count == self.slots[from].count + end + + -- Transfer the items + self:select(from) + turtle.transferTo(to, count) + + self:update() + + return return_value +end + + +-- Scan inventory and store updates +function Inventory:update() + local slots, items = {}, {} + + for i = 1, 16 do + local data = turtle.getItemDetail(i) + + if data then + slots[i] = data + + if items[data.name] then + table.insert(items[data.name], i) + + else + items[data.name] = {i} + end + end + end + + self.slots = slots + self.items = items +end + + +-- Returns wether or not the inventory contains the given item +-- +-- @param item_name item name to look for +-- @return bool wether or not the item is in the inventory +function Inventory:has(item_name) + return self.items[item_name] ~= nil +end + + +-- Returns wether the requested slot is free +-- +-- @param slot slot to check +function Inventory:is_free(slot) + return self.slots[slot] == nil +end + + +-- Compact an item in the inventory; this means moving as much of the items to +-- as little of the used slots as possible +-- +-- @param item_name item to compact +function Inventory:sort_item(item_name) + -- atm we assume the item is in the inventory + local slots = self.items[item_name] + + local i, j = 1, 2 + + while j <= #slots do + if self:transfer(slots[j], slots[i]) then + j = j + 1 + + else + i = i + 1 + j = i + 1 + end + end +end + + +-- Compact the inventory; this means moving all items to the lowest possible +-- slots +function Inventory:sort() + -- Sort all items + for item, _ in pairs(self.items) do + self:sort_item(item) + end + + -- Move them all to lowest slots + -- TODO implement this +end + + +return {Inventory=Inventory}