Finished autocrafting

master
D4VID 11 months ago
parent f59beed41a
commit 048fa77cd6

@ -1,6 +1,7 @@
local component = require("component")
local robot = require("robot")
local sides = require("sides")
local event = require("event")
local recipes = require('recipes')
@ -30,6 +31,17 @@ local function parse_item(str, delimiter)
return string.sub(str, 1, pos - 1), tonumber(string.sub(str, pos + 1))
end
---duplicate the table t
---@param t table
---@return table
local function clone(t)
local t2 = {}
for k, v in pairs(t) do
t2[k] = v
end
return t2
end
---add count to the selected key, or create it if it doesn't exist
---@param dict table
---@param key string
@ -53,6 +65,21 @@ local function append(a, b)
return a
end
---Ask the user if they want to proceed
---@return boolean
local function confirm()
while true do
print("Proceed? [y/n]")
local _, _, ascii, _, _ = event.pull("key_down")
local ch = string.char(ascii)
if ch == 'y' then
return true
elseif ch == 'n' then
return false
end
end
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()
@ -87,7 +114,7 @@ local function store_item()
-- check if all items have been stored
local remaining = inventory.getStackInInternalSlot()
if not remaining then
print('Stored successfully')
-- print('Stored successfully')
return true
end
end
@ -106,7 +133,7 @@ local function store_item()
print('Cannot store item: ' .. error .. "\n")
return false
else
print('Stored successfully')
-- print('Stored successfully')
return true
end
else
@ -153,8 +180,11 @@ local function craft_single_recipe(recipe)
return false
end
for i, ingredient in pairs(recipe.shape) do
print('Fetching ' .. ingredient)
fetch_item(ingredient, slot_map[i])
-- print('Fetching ' .. ingredient)
if not fetch_item(ingredient, slot_map[i]) then
print('Failed to fetch ' .. ingredient)
confirm()
end
end
-- select slot for the result
@ -172,68 +202,85 @@ end
---comment
---@param recipe table
---@param available_items table
---@return boolean success
---@param available_items table available initially
---@param currently_available table available from previous crafring
---@return table total_required_items
---@return table recipe_crafting_order array of recipes
local function craft_recipe_recursion(recipe, available_items)
local function craft_recipe_recursion(recipe, available_items, currently_available)
local total_required_items = {}
local total_crafting_order = { recipe }
local total_crafting_order = {}
-- go through all the required ingredients
for item, count in pairs(recipe.requires) do
local available = available_items[item]
-- check if some crafting result provided this item
local available = currently_available[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)
-- print('I have ' .. count .. ' ' .. item .. ' from previous crafting')
-- remove it from tracked available items so if other recipe requires it, it needs to craft it
available_items[item] = available_items[item] - count
currently_available[item] = currently_available[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, {}, {}
-- check if there is enough in the main available storage
available = available_items[item]
if not available then
available = 0
end
if available >= required_count then
-- print('I have ' .. required_count .. ' ' .. item .. ' available')
add(total_required_items, item, required_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
-- update count
required_count = required_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 = number_of_crafting_operations * sub_recipe.count - required_count
-- print(' Will make ' .. number_of_crafting_operations .. ' crafting operations')
-- print(' That will produce ' .. excess .. ' items I can use later')
-- do the crafting
local current_crafting_order = {}
for _ = 1, number_of_crafting_operations do
local required_items, crafting_order = craft_recipe_recursion(sub_recipe, available_items, currently_available)
for k, v in pairs(required_items) do
add(total_required_items, k, v)
end
current_crafting_order = append(current_crafting_order, crafting_order)
end
for k, v in pairs(required_items) do
add(total_required_items, k, v)
total_crafting_order = append(total_crafting_order, current_crafting_order)
if excess > 0 then
add(currently_available, item, excess)
end
-- append
current_crafting_order = append(current_crafting_order, crafting_order)
else
-- print('Need ' .. required_count .. ' more ' .. item)
add(total_required_items, item, count)
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
-- add the recipe it self to the end
total_crafting_order[#total_crafting_order+1] = recipe
return total_required_items, total_crafting_order
end
---accepts a recipe table
---@param item string
---@return boolean
local function craft_recipe(item)
local function craft_item(item)
print('Trying to craft ' .. item)
local recipe = recipes[item]
if not recipe then
@ -247,14 +294,29 @@ local function craft_recipe(item)
return false
end
local success, required_items, crafting_order = craft_recipe_recursion(recipe, available_items)
if not success then
print('Failed')
local required_items, crafting_order = craft_recipe_recursion(recipe, clone(available_items), {})
print('\nRequires these items:')
local failed = false
for required_item, required_count in pairs(required_items) do
local available = available_items[required_item]
if not available then
available = 0
end
if available < required_count then
print(available .. "/" .. required_count .. "\t" .. required_item .. "\t- Missing " .. required_count - available)
failed = true
else
print(available .. "/" .. required_count .. "\t" .. required_item)
end
end
if failed then
return false
end
print('\nRequires these items:')
for k, v in pairs(required_items) do
print(k, v)
if not confirm() then
print('Operation cancelled')
return false
end
print('\nCrafting in order:')
@ -262,6 +324,10 @@ local function craft_recipe(item)
print(i, rec.result)
end
if not confirm() then
print('Operation cancelled')
return false
end
-- proceed to crafting the things
for i, rec in ipairs(crafting_order) do
@ -275,23 +341,15 @@ local function craft_recipe(item)
return true
end
-- local target = ...
local target = ...
-- if not target then
-- print("Usage: craft <item>")
-- return
-- end
-- craft_recipe('minecraft:iron_pickaxe;0')
craft_recipe('opencomputers:keyboard;0')
if not target then
print("Usage: craft <item>")
return
end
-- store_item()
craft_item(target)
-- 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
-- craft_item('minecraft:iron_pickaxe;0')
-- craft_item('opencomputers:keyboard;0')
-- craft_item('opencomputers:material;10')

@ -2,9 +2,13 @@
-- pair of name (string id) and damage separated by ';'
-- Iron Pickaxe
-- ['minecraft:iron_pickaxe;0'] = {
-- result = 'minecraft:iron_pickaxe;0',
-- count = 1,
-- ingredients = {
-- result = 'minecraft:iron_pickaxe;0',
-- count = 1,
-- requires = {
-- ['minecraft:iron_ingot;0'] = 3,
-- ['minecraft:stick;0'] = 2,
-- },
-- shape = {
-- 'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0',
-- nil, 'minecraft:stick;0', nil,
-- nil, 'minecraft:stick;0', nil,
@ -38,13 +42,26 @@ return {
nil, nil, nil,
}
},
-- Chest
['minecraft:chest;0'] = {
result = 'minecraft:chest;0',
count = 1,
requires = {
['minecraft:planks;0'] = 8,
},
shape = {
'minecraft:planks;0', 'minecraft:planks;0', 'minecraft:planks;0',
'minecraft:planks;0', nil, 'minecraft:planks;0',
'minecraft:planks;0', 'minecraft:planks;0', 'minecraft:planks;0',
}
},
-- Iron Pickaxe
['minecraft:iron_pickaxe;0'] = {
result = 'minecraft:iron_pickaxe;0',
count = 1,
requires = {
['minecraft:iron_ingot;0'] = 3,
['minecraft:stick;0'] = 5,
['minecraft:stick;0'] = 2,
},
shape = {
'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0',
@ -65,7 +82,20 @@ return {
nil, nil, nil,
}
},
-- gold nugget
-- Iron Bars
['minecraft:iron_bars;0'] = {
result = 'minecraft:iron_bars;0',
count = 16,
requires = {
['minecraft:iron_ingot;0'] = 6,
},
shape = {
nil, nil, nil,
'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0',
'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0', 'minecraft:iron_ingot;0',
}
},
-- Gold nugget
['minecraft:gold_nugget;0'] = {
result = 'minecraft:gold_nugget;0',
count = 9,
@ -91,6 +121,62 @@ return {
nil, nil, nil,
}
},
-- Hopper
['minecraft:hopper;0'] = {
result = 'minecraft:hopper;0',
count = 1,
requires = {
['minecraft:iron_ingot;0'] = 5,
['minecraft:chest;0'] = 1,
},
shape = {
'minecraft:iron_ingot;0', nil, 'minecraft:iron_ingot;0',
'minecraft:iron_ingot;0', 'minecraft:chest;0', 'minecraft:iron_ingot;0',
nil, 'minecraft:iron_ingot;0', nil,
}
},
-- Dropper
['minecraft:dropper;0'] = {
result = 'minecraft:dropper;0',
count = 1,
requires = {
['minecraft:cobblestone;0'] = 7,
['minecraft:redstone;0'] = 1,
},
shape = {
'minecraft:cobblestone;0', 'minecraft:cobblestone;0', 'minecraft:cobblestone;0',
'minecraft:cobblestone;0', nil, 'minecraft:cobblestone;0',
'minecraft:cobblestone;0', 'minecraft:redstone;0', 'minecraft:cobblestone;0',
}
},
-- Lever
['minecraft:lever;0'] = {
result = 'minecraft:lever;0',
count = 1,
requires = {
['minecraft:stick;0'] = 1,
['minecraft:cobblestone;0'] = 1,
},
shape = {
nil, 'minecraft:stick;0', nil,
nil, 'minecraft:cobblestone;0', nil,
nil, nil, nil,
}
},
-- Redstone Torch
['minecraft:redstone_torch;0'] = {
result = 'minecraft:redstone_torch;0',
count = 1,
requires = {
['minecraft:stick;0'] = 1,
['minecraft:redstone;0'] = 1,
},
shape = {
nil, 'minecraft:redstone;0', nil,
nil, 'minecraft:stick;0', nil,
nil, nil, nil,
}
},
-- Clock
['minecraft:clock;0'] = {
result = 'minecraft:clock;0',
@ -105,6 +191,22 @@ return {
nil, 'minecraft:gold_ingot;0', nil,
}
},
-- Piston
['minecraft:piston;0'] = {
result = 'minecraft:piston;0',
count = 1,
requires = {
['minecraft:iron_ingot;0'] = 1,
['minecraft:redstone;0'] = 1,
['minecraft:planks;0'] = 3,
['minecraft:cobblestone;0'] = 4,
},
shape = {
'minecraft:planks;0', 'minecraft:planks;0', 'minecraft:planks;0',
'minecraft:cobblestone;0', 'minecraft:iron_ingot;0', 'minecraft:cobblestone;0',
'minecraft:cobblestone;0', 'minecraft:redstone;0', 'minecraft:cobblestone;0',
}
},
-- Button
['minecraft:stone_button;0'] = {
result = 'minecraft:stone_button;0',
@ -118,6 +220,24 @@ return {
nil, nil, nil,
}
},
-----------------------------------------------------------------------------------------
-- Card Base
['opencomputers:material;5'] = {
result = 'opencomputers:material;5',
count = 1,
requires = {
['minecraft:iron_nugget;0'] = 3,
['minecraft:gold_nugget;0'] = 1,
['opencomputers:material;4'] = 1, -- Printed Circuit Board
},
shape = {
'minecraft:iron_nugget;0', nil, nil,
'minecraft:iron_nugget;0', 'opencomputers:material;4', nil,
'minecraft:iron_nugget;0', 'minecraft:gold_nugget;0', nil,
}
},
-- Transistor
['opencomputers:material;6'] = {
result = 'opencomputers:material;6',
@ -196,6 +316,19 @@ return {
'minecraft:gold_nugget;0', 'opencomputers:material;6', 'minecraft:gold_nugget;0',
}
},
-- Disk Platter
['opencomputers:material;12'] = {
result = 'opencomputers:material;12',
count = 1,
requires = {
['minecraft:iron_nugget;0'] = 4,
},
shape = {
nil, 'minecraft:iron_nugget;0', nil,
'minecraft:iron_nugget;0', nil, 'minecraft:iron_nugget;0',
nil, 'minecraft:iron_nugget;0', nil,
}
},
-- Button Group
['opencomputers:material;14'] = {
result = 'opencomputers:material;14',
@ -235,6 +368,9 @@ return {
'minecraft:stone_button;0', 'minecraft:stone_button;0', 'minecraft:stone_button;0',
}
},
-----------------------------------------------------------------------------------------
-- Keyboard
['opencomputers:keyboard;0'] = {
result = 'opencomputers:material;0',
@ -250,4 +386,173 @@ return {
'opencomputers:material;14', 'opencomputers:material;15', 'opencomputers:material;16',
}
},
-- Screen (Tier 1)
['opencomputers:screen1;0'] = {
result = 'opencomputers:screen1;0',
count = 1,
requires = {
['minecraft:iron_ingot;0'] = 4,
['minecraft:redstone;0'] = 3,
['opencomputers:material;7'] = 1, -- Microchip (Tier 1)
['minecraft:glass;0'] = 1,
},
shape = {
'minecraft:iron_ingot;0', 'minecraft:redstone;0', 'minecraft:iron_ingot;0',
'minecraft:redstone:0', 'opencomputers:material:7;0', 'minecraft:glass:0',
'minecraft:iron_ingot;0', 'minecraft:redstone:0', 'minecraft:iron_ingot;0',
}
},
-- Memory (Tier 1)
['opencomputers:component;6'] = {
result = 'opencomputers:component;6',
count = 1,
requires = {
['opencomputers:material;7'] = 2, -- Microchip (Tier 1)
['minecraft:iron_nugget;0'] = 1,
['opencomputers:material;4'] = 1, -- Printed Circuit Board
},
shape = {
nil, nil, nil,
'opencomputers:material;7', 'minecraft:iron_nugget;0', 'opencomputers:material;7',
nil, 'opencomputers:material;4', nil,
}
},
-- Graphics Card (Tier 1)
['opencomputers:card;1'] = {
result = 'opencomputers:card;1',
count = 1,
requires = {
['opencomputers:material;7'] = 1, -- Microchip (Tier 1)
['opencomputers:material;10'] = 1, -- Arithmetic Logic Unit (ALU)
['opencomputers:component;6'] = 1, -- Memoty (Tier 1)
['opencomputers:material;5'] = 1, -- Card Base
},
shape = {
nil, nil, nil,
'opencomputers:material;7', 'opencomputers:material;10', 'opencomputers:component;6',
nil, 'opencomputers:material;5', nil,
}
},
-- EEPROM
['opencomputers:storage;0'] = {
result = 'opencomputers:storage;0',
count = 1,
requires = {
['opencomputers:material;6'] = 1, -- Transistor
['opencomputers:material;7'] = 1, -- Microchip (Tier 1)
['minecraft:gold_nugget;0'] = 4,
['minecraft:paper;0'] = 2,
['minecraft:redstone_torch;0'] = 1,
},
shape = {
'minecraft:gold_nugget;0', 'opencomputers:material;6', 'minecraft:gold_nugget;0',
'minecraft:paper;0', 'opencomputers:material;7', 'minecraft:paper;0',
'minecraft:gold_nugget;0', 'minecraft:redstone_torch;0', 'minecraft:gold_nugget;0',
}
},
-- Floppy Disk
['opencomputers:storage;1'] = {
result = 'opencomputers:storage;1',
count = 1,
requires = {
['opencomputers:material;12'] = 1, -- Disk Platter
['minecraft:iron_nugget;0'] = 4,
['minecraft:paper;0'] = 3,
['minecraft:lever;0'] = 1,
},
shape = {
'minecraft:iron_nugget;0', 'minecraft:lever;0', 'minecraft:iron_nugget;0',
'minecraft:paper;0', 'opencomputers:material;12', 'minecraft:paper;0',
'minecraft:iron_nugget;0', 'minecraft:paper;0', 'minecraft:iron_nugget;0',
}
},
-- Hard Disk Drive (Tier 1)
['opencomputers:storage;2'] = {
result = 'opencomputers:storage;2',
count = 1,
requires = {
['opencomputers:material;7'] = 2, -- Microchip (Tier 1)
['opencomputers:material;4'] = 1, -- Printed Circuit Board
['opencomputers:material;12'] = 3, -- Disk Platter
['minecraft:iron_ingot;0'] = 2,
['minecraft:piston;0'] = 1,
},
shape = {
'opencomputers:material;7', 'opencomputers:material;12', 'minecraft:iron_ingot;0',
'opencomputers:material;4', 'opencomputers:material;12', 'minecraft:piston;0',
'opencomputers:material;7', 'opencomputers:material;12', 'minecraft:iron_ingot;0',
}
},
-- Computer Case (Tier 2)
['opencomputers:case2;0'] = {
result = 'opencomputers:case2;0',
count = 1,
requires = {
['opencomputers:material;8'] = 1, -- Microchip (Tier 2)
['opencomputers:material;4'] = 1, -- Printed Circuit Board
['minecraft:gold_ingot;0'] = 4,
['minecraft:iron_bars;0'] = 2,
['minecraft:chest;0'] = 1,
},
shape = {
'minecraft:gold_ingot;0', 'opencomputers:material;8', 'minecraft:gold_ingot;0',
'minecraft:iron_bars;0', 'minecraft:chest;0', 'minecraft:iron_bars;0',
'minecraft:gold_ingot;0', 'opencomputers:material;4', 'minecraft:gold_ingot;0',
}
},
-- Analyzer
['opencomputers:tool;0'] = {
result = 'opencomputers:tool;0',
count = 1,
requires = {
['opencomputers:material;6'] = 1, -- Transistor
['opencomputers:material;4'] = 1, -- Printed Circuit Board
['minecraft:gold_nugget;0'] = 2,
['minecraft:redstone_torch;0'] = 1,
},
shape = {
'minecraft:redstone_torch;0', nil, nil,
'opencomputers:material;6', 'minecraft:gold_nugget;0', nil,
'opencomputers:material;4', 'minecraft:gold_nugget;0', nil,
}
},
-----------------------------------------------------------------------------------------
-- Inventory Upgrade
['opencomputers:upgrade;17'] = {
result = 'opencomputers:upgrade;17',
count = 1,
requires = {
['opencomputers:material;7'] = 1, -- Microchip (Tier 1)
['minecraft:planks;0'] = 4,
['minecraft:hopper;0'] = 1,
['minecraft:dropper;0'] = 1,
['minecraft:chest;0'] = 1,
['minecraft:piston;0'] = 1,
},
shape = {
'minecraft:planks;0', 'minecraft:hopper;0', 'minecraft:planks;0',
'minecraft:dropper;0', 'minecraft:chest;0', 'minecraft:piston;0',
'minecraft:planks;0', 'opencomputers:material;7', 'minecraft:planks;0',
}
},
-- Inventory Controler Upgrade
['opencomputers:upgrade;18'] = {
result = 'opencomputers:upgrade;18',
count = 1,
requires = {
['opencomputers:material;8'] = 1, -- Microchip (Tier 2)
['opencomputers:material;4'] = 1, -- Printed Circuit Board
['opencomputers:tool;0'] = 1, -- Analyzer
['minecraft:gold_ingot;0'] = 4,
['minecraft:dropper;0'] = 1,
['minecraft:piston;0'] = 1,
},
shape = {
'minecraft:gold_ingot;0', 'opencomputers:tool;0', 'minecraft:gold_ingot;0',
'minecraft:dropper;0', 'opencomputers:material;8', 'minecraft:piston;0',
'minecraft:gold_ingot;0', 'opencomputers:material;4', 'minecraft:gold_ingot;0',
}
},
}

Loading…
Cancel
Save