local component = require("component") local robot = require("robot") local sides = require("sides") local crafting = component.crafting local inventory = component.inventory_controller RESULT_SLOT = 4 local iron_pickaxe_recipe = { result = { item = { 'minecraft:iron_pickaxe', 0 }, count = 1, }, ingredients = { -- pair of name (string id) and damage separated by ';' 'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0', nil, 'minecraft:stick;0', nil, nil, 'minecraft:stick;0', nil, } } -- robots inventory is 4 wide and crafting uses the top left portion local slot_map = { 1, 2, 3, 5, 6, 7, 9, 10, 11 } ---"item" being pair string id and damage separated by ';' eg. "minecraft:wool;3" ---returns "minecraft:wool", 3 ---@param str string ---@param delimiter string ---@return string|nil ---@return number|nil local function parse_item(str, delimiter) local pos = string.find(str, delimiter) if not pos then return nil,nil end return string.sub(str, 1, pos-1), tonumber(string.sub(str, pos+1)) end ---read the facing inventory and return a table of item names and their count or nil if not facing an inventory ---@return table|nil local function read_chest_contents() local contents = {} local size = inventory.getInventorySize(sides.forward) if not size then return nil end for slot = 1, size do local stack = inventory.getStackInSlot(sides.forward, slot) if stack then local name = stack.name .. ";" .. stack.damage if contents[name] then contents[name] = contents[name] + stack.size else contents[name] = stack.size end end end return contents end ---store the item in the selected slot into the facing inventory ---@return boolean local function store_item() -- check if that item is present in the inventory local item = inventory.getStackInInternalSlot() local size = inventory.getInventorySize(sides.forward) local empty_slot = -1 for slot = 1, size do local stack = inventory.getStackInSlot(sides.forward, slot) if stack then if stack.name == item.name then inventory.dropIntoSlot(sides.forward, slot) -- check if all items have been stored local remaining = inventory.getStackInInternalSlot() if not remaining then print('Stored successfully') return true end end else if empty_slot == -1 then empty_slot = slot end end end -- item not present in inventory if empty_slot ~= -1 then -- store in first empty slot local result, error = inventory.dropIntoSlot(sides.forward, empty_slot) if not result then print('Cannot store item: ' .. error .. "\n") return false else print('Stored successfully') return true end else print('Cannot store item - Inventory full') return false end end ---Search the facing chest for "item" and take "count" items and place them in "slot" ---"item" being pair string id and damage separated by ';' eg. "minecraft:wool;3" ---Returns number of items fetched ---@param item string ---@param output_slot number ---@return boolean local function fetch_item(item, output_slot) local name, damage = parse_item(item, ";") robot.select(output_slot) local size = inventory.getInventorySize(sides.forward) if not size then print('Not facing a chest') return false end for slot = 1, size do local stack = inventory.getStackInSlot(sides.forward, slot) if stack then if stack.name == name and stack.damage == damage then inventory.suckFromSlot(sides.forward, slot, 1) return true end end end print('Missing ' .. item) return false end ---accepts a recipe table containing result and ingredients ---@param recipe table ---@return boolean local function craft_recipe(recipe) if inventory.getStackInInternalSlot(RESULT_SLOT) then print('Cannot craft - output slot occupied') return false end for i, ingredient in pairs(recipe.ingredients) do print('Fetching ' .. ingredient) fetch_item(ingredient, slot_map[i]) end -- select slot for the result robot.select(RESULT_SLOT) -- craft the resulting item local crafted = crafting.craft(1) if not crafted then print('Crafting failed') return false end return store_item() end -- local target = ... -- if not target then -- print("Usage: craft ") -- return -- end craft_recipe(iron_pickaxe_recipe) -- store_item() -- local contents = read_chest_contents() -- if contents then -- for k,v in pairs(contents) do -- print(k,v) -- end -- else -- print('Not facing a chest') -- end