Actuall autocrafting

master
D4VID 12 months ago
parent 2db5040c52
commit f59beed41a

@ -2,24 +2,13 @@ local component = require("component")
local robot = require("robot")
local sides = require("sides")
local recipes = require('recipes')
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,
@ -36,9 +25,32 @@ local slot_map = {
local function parse_item(str, delimiter)
local pos = string.find(str, delimiter)
if not pos then
return nil,nil
return nil, nil
end
return string.sub(str, 1, pos - 1), tonumber(string.sub(str, pos + 1))
end
---add count to the selected key, or create it if it doesn't exist
---@param dict table
---@param key string
---@param count number
local function add(dict, key, count)
if dict[key] then
dict[key] = dict[key] + count
else
dict[key] = count
end
end
---append the array b to the end of array a
---@param a table
---@param b table
---@return table
local function append(a, b)
for i = 1, #b do
a[#a + 1] = b[i]
end
return string.sub(str, 1, pos-1), tonumber(string.sub(str, pos+1))
return a
end
---read the facing inventory and return a table of item names and their count or nil if not facing an inventory
@ -53,11 +65,7 @@ local function read_chest_contents()
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
add(contents, name, stack.size)
end
end
return contents
@ -139,12 +147,12 @@ end
---accepts a recipe table containing result and ingredients
---@param recipe table
---@return boolean
local function craft_recipe(recipe)
local function craft_single_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
for i, ingredient in pairs(recipe.shape) do
print('Fetching ' .. ingredient)
fetch_item(ingredient, slot_map[i])
end
@ -162,6 +170,111 @@ local function craft_recipe(recipe)
return store_item()
end
---comment
---@param recipe table
---@param available_items table
---@return boolean success
---@return table total_required_items
---@return table recipe_crafting_order array of recipes
local function craft_recipe_recursion(recipe, available_items)
local total_required_items = {}
local total_crafting_order = { recipe }
for item, count in pairs(recipe.requires) do
local available = available_items[item]
if not available then
available = 0
end
if available >= count then
print('I have ' .. count .. ' ' .. item)
-- don't have to craft anything
add(total_required_items, item, count)
-- remove it from tracked available items so if other recipe requires it, it needs to craft it
available_items[item] = available_items[item] - count
else
local required_count = count - available
print('Missing ' .. required_count .. ' ' .. item)
-- check if I can craft it
local sub_recipe = recipes[item]
if sub_recipe then
print('Trying to craft ' .. item)
local number_of_crafting_operations = math.ceil(required_count / sub_recipe.count)
local excess = required_count % sub_recipe.count
print(' Will make ' .. number_of_crafting_operations .. ' crafting operations')
print(' That will produce ' .. excess .. ' items I can use later')
local current_crafting_order = {}
for _ = 1, number_of_crafting_operations do
local success, required_items, crafting_order = craft_recipe_recursion(sub_recipe, available_items)
if not success then
return false, {}, {}
end
for k, v in pairs(required_items) do
add(total_required_items, k, v)
end
-- append
current_crafting_order = append(current_crafting_order, crafting_order)
end
-- prepend
total_crafting_order = append(current_crafting_order, total_crafting_order)
if excess > 0 then
add(available_items, item, excess)
end
else
print('Need ' .. required_count .. ' more ' .. item)
return false, {}, {}
end
end
end
return true, total_required_items, total_crafting_order
end
---accepts a recipe table
---@param item string
---@return boolean
local function craft_recipe(item)
print('Trying to craft ' .. item)
local recipe = recipes[item]
if not recipe then
print('Cannot craft ' .. item)
return false
end
local available_items = read_chest_contents()
if not available_items then
print('Not facing a chest')
return false
end
local success, required_items, crafting_order = craft_recipe_recursion(recipe, available_items)
if not success then
print('Failed')
return false
end
print('\nRequires these items:')
for k, v in pairs(required_items) do
print(k, v)
end
print('\nCrafting in order:')
for i, rec in ipairs(crafting_order) do
print(i, rec.result)
end
-- proceed to crafting the things
for i, rec in ipairs(crafting_order) do
print('Step #' .. i .. ' - ' .. rec.result)
if not craft_single_recipe(rec) then
print('Unexpected error')
return false
end
end
return true
end
-- local target = ...
-- if not target then
@ -169,7 +282,8 @@ end
-- return
-- end
craft_recipe(iron_pickaxe_recipe)
-- craft_recipe('minecraft:iron_pickaxe;0')
craft_recipe('opencomputers:keyboard;0')
-- store_item()

@ -0,0 +1,253 @@
-- template:
-- pair of name (string id) and damage separated by ';'
-- Iron Pickaxe
-- ['minecraft:iron_pickaxe;0'] = {
-- result = 'minecraft:iron_pickaxe;0',
-- count = 1,
-- ingredients = {
-- 'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0',
-- nil, 'minecraft:stick;0', nil,
-- nil, 'minecraft:stick;0', nil,
-- }
-- },
return {
-- Oak planks
['minecraft:planks;0'] = {
result = 'minecraft:planks;0',
count = 4,
requires = {
['minecraft:log;0'] = 1,
},
shape = {
nil, nil, nil,
nil, 'minecraft:log;0', nil,
nil, nil, nil,
}
},
-- Sticks
['minecraft:stick;0'] = {
result = 'minecraft:stick;0',
count = 4,
requires = {
['minecraft:planks;0'] = 2,
},
shape = {
nil, 'minecraft:planks;0', nil,
nil, 'minecraft:planks;0', nil,
nil, nil, nil,
}
},
-- Iron Pickaxe
['minecraft:iron_pickaxe;0'] = {
result = 'minecraft:iron_pickaxe;0',
count = 1,
requires = {
['minecraft:iron_ingot;0'] = 3,
['minecraft:stick;0'] = 5,
},
shape = {
'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0',
nil, 'minecraft:stick;0', nil,
nil, 'minecraft:stick;0', nil,
}
},
-- Iron nugget
['minecraft:iron_nugget;0'] = {
result = 'minecraft:iron_nugget;0',
count = 9,
requires = {
['minecraft:iron_ingot;0'] = 1,
},
shape = {
'minecraft:iron_ingot;0', nil, nil,
nil, nil, nil,
nil, nil, nil,
}
},
-- gold nugget
['minecraft:gold_nugget;0'] = {
result = 'minecraft:gold_nugget;0',
count = 9,
requires = {
['minecraft:gold_ingot;0'] = 1,
},
shape = {
'minecraft:gold_ingot;0', nil, nil,
nil, nil, nil,
nil, nil, nil,
}
},
-- Paper
['minecraft:paper;0'] = {
result = 'minecraft:paper;0',
count = 3,
requires = {
['minecraft:reeds;0'] = 3,
},
shape = {
nil, nil, nil,
'minecraft:reeds;0', 'minecraft:reeds;0', 'minecraft:reeds;0',
nil, nil, nil,
}
},
-- Clock
['minecraft:clock;0'] = {
result = 'minecraft:clock;0',
count = 1,
requires = {
['minecraft:gold_ingot;0'] = 4,
['minecraft:redstone;0'] = 1,
},
shape = {
nil, 'minecraft:gold_ingot;0', nil,
'minecraft:gold_ingot;0', 'minecraft:redstone;0', 'minecraft:gold_ingot;0',
nil, 'minecraft:gold_ingot;0', nil,
}
},
-- Button
['minecraft:stone_button;0'] = {
result = 'minecraft:stone_button;0',
count = 1,
requires = {
['minecraft:stone;0'] = 1,
},
shape = {
nil, nil, nil,
nil, 'minecraft:stone;0', nil,
nil, nil, nil,
}
},
-- Transistor
['opencomputers:material;6'] = {
result = 'opencomputers:material;6',
count = 8,
requires = {
['minecraft:iron_ingot;0'] = 3,
['minecraft:gold_nugget;0'] = 2,
['minecraft:paper;0'] = 1,
['minecraft:redstone;0'] = 1,
},
shape = {
'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0',
'minecraft:gold_nugget;0', 'minecraft:paper;0', 'minecraft:gold_nugget;0',
nil, 'minecraft:redstone;0', nil,
}
},
-- Microchip (Tier 1)
['opencomputers:material;7'] = {
result = 'opencomputers:material;7',
count = 8,
requires = {
['minecraft:iron_nugget;0'] = 6,
['minecraft:redstone;0'] = 2,
['opencomputers:material;6'] = 1, -- Transistor
},
shape = {
'minecraft:iron_nugget;0', 'minecraft:iron_nugget;0', 'minecraft:iron_nugget;0',
'minecraft:redstone;0', 'opencomputers:material;6', 'minecraft:redstone;0',
'minecraft:iron_nugget;0', 'minecraft:iron_nugget;0', 'minecraft:iron_nugget;0',
}
},
-- Microchip (Tier 2)
['opencomputers:material;8'] = {
result = 'opencomputers:material;8',
count = 4,
requires = {
['minecraft:gold_nugget;0'] = 6,
['minecraft:redstone;0'] = 2,
['opencomputers:material;6'] = 1, -- Transistor
},
shape = {
'minecraft:gold_nugget;0', 'minecraft:gold_nugget;0', 'minecraft:gold_nugget;0',
'minecraft:redstone;0', 'opencomputers:material;6', 'minecraft:redstone;0',
'minecraft:gold_nugget;0', 'minecraft:gold_nugget;0', 'minecraft:gold_nugget;0',
}
},
-- Arithmetic Logic Unit (ALU)
['opencomputers:material;10'] = {
result = 'opencomputers:material;10',
count = 1,
requires = {
['minecraft:iron_nugget;0'] = 4,
['opencomputers:material;6'] = 3, -- Transistor
['minecraft:redstone;0'] = 1,
['opencomputers:material;7'] = 1, -- Microchip (Tier 1)
},
shape = {
'minecraft:iron_nugget;0', 'minecraft:redstone;0', 'minecraft:iron_nugget;0',
'opencomputers:material;6', 'opencomputers:material;7', 'opencomputers:material;6',
'minecraft:iron_nugget;0', 'opencomputers:material;6', 'minecraft:iron_nugget;0',
}
},
-- Control Unit (CU)
['opencomputers:material;11'] = {
result = 'opencomputers:material;11',
count = 1,
requires = {
['minecraft:gold_nugget;0'] = 4,
['opencomputers:material;6'] = 3, -- Transistor
['minecraft:redstone;0'] = 1,
['minecraft:clock;0'] = 1,
},
shape = {
'minecraft:gold_nugget;0', 'minecraft:redstone;0', 'minecraft:gold_nugget;0',
'opencomputers:material;6', 'minecraft:clock;0', 'opencomputers:material;6',
'minecraft:gold_nugget;0', 'opencomputers:material;6', 'minecraft:gold_nugget;0',
}
},
-- Button Group
['opencomputers:material;14'] = {
result = 'opencomputers:material;14',
count = 1,
requires = {
['minecraft:stone_button;0'] = 6,
},
shape = {
nil, nil, nil,
'minecraft:stone_button;0', 'minecraft:stone_button;0', 'minecraft:stone_button;0',
'minecraft:stone_button;0', 'minecraft:stone_button;0', 'minecraft:stone_button;0',
}
},
-- Arrow Keys
['opencomputers:material;15'] = {
result = 'opencomputers:material;15',
count = 1,
requires = {
['minecraft:stone_button;0'] = 4,
},
shape = {
nil, nil, nil,
nil, 'minecraft:stone_button;0', nil,
'minecraft:stone_button;0', 'minecraft:stone_button;0', 'minecraft:stone_button;0',
}
},
-- Numeric Keypad
['opencomputers:material;16'] = {
result = 'opencomputers:material;16',
count = 1,
requires = {
['minecraft:stone_button;0'] = 9,
},
shape = {
'minecraft:stone_button;0', 'minecraft:stone_button;0', 'minecraft:stone_button;0',
'minecraft:stone_button;0', 'minecraft:stone_button;0', 'minecraft:stone_button;0',
'minecraft:stone_button;0', 'minecraft:stone_button;0', 'minecraft:stone_button;0',
}
},
-- Keyboard
['opencomputers:keyboard;0'] = {
result = 'opencomputers:material;0',
count = 1,
requires = {
['opencomputers:material;14'] = 4,
['opencomputers:material;15'] = 1,
['opencomputers:material;16'] = 1,
},
shape = {
nil, nil, nil,
'opencomputers:material;14', 'opencomputers:material;14', 'opencomputers:material;14',
'opencomputers:material;14', 'opencomputers:material;15', 'opencomputers:material;16',
}
},
}
Loading…
Cancel
Save