Autocrafter multi group ingredient (#115)
* check for non-zero group value in theory groups can have negative values too. * fix #114 multi group recipe items Fix the bug that prevented crafting with recipes that had ingredients that need to match multiple groups. * comments and whitespace changes * fix faulty empty table check
This commit is contained in:
parent
8828183bef
commit
1577af738f
@ -4,6 +4,7 @@ local S = minetest.get_translator("pipeworks")
|
|||||||
local autocrafterCache = {}
|
local autocrafterCache = {}
|
||||||
|
|
||||||
local craft_time = 1
|
local craft_time = 1
|
||||||
|
local next = next
|
||||||
|
|
||||||
local function count_index(invlist)
|
local function count_index(invlist)
|
||||||
local index = {}
|
local index = {}
|
||||||
@ -48,7 +49,9 @@ local function get_matching_craft(output_name, example_recipe)
|
|||||||
elseif recipe_item_name:sub(1, 6) == "group:" then
|
elseif recipe_item_name:sub(1, 6) == "group:" then
|
||||||
group = recipe_item_name:sub(7)
|
group = recipe_item_name:sub(7)
|
||||||
for example_item_name, _ in pairs(index_example) do
|
for example_item_name, _ in pairs(index_example) do
|
||||||
if minetest.get_item_group(example_item_name, group) > 0 then
|
if minetest.get_item_group(
|
||||||
|
example_item_name, group) ~= 0
|
||||||
|
then
|
||||||
score = score + 1
|
score = score + 1
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@ -89,22 +92,27 @@ local function get_craft(pos, inventory, hash)
|
|||||||
return craft
|
return craft
|
||||||
end
|
end
|
||||||
|
|
||||||
-- From a consumption table with groups and an inventory index, build
|
-- From a consumption table with groups and an inventory index,
|
||||||
-- a consumption table without groups
|
-- build a consumption table without groups
|
||||||
local function calculate_consumption(inv_index, consumption_with_groups)
|
local function calculate_consumption(inv_index, consumption_with_groups)
|
||||||
inv_index = table.copy(inv_index)
|
inv_index = table.copy(inv_index)
|
||||||
consumption_with_groups = table.copy(consumption_with_groups)
|
consumption_with_groups = table.copy(consumption_with_groups)
|
||||||
|
|
||||||
|
-- table of items to actually consume
|
||||||
local consumption = {}
|
local consumption = {}
|
||||||
local groups = {}
|
-- table of ingredients defined as one or more groups each
|
||||||
|
local grouped_ingredients = {}
|
||||||
|
|
||||||
-- First consume all non-group requirements
|
-- First consume all non-group requirements
|
||||||
-- This is done to avoid consuming a non-group item which is also
|
-- This is done to avoid consuming a non-group item which
|
||||||
-- in a group
|
-- is also in a group
|
||||||
for key, count in pairs(consumption_with_groups) do
|
for key, count in pairs(consumption_with_groups) do
|
||||||
if key:sub(1, 6) == "group:" then
|
if key:sub(1, 6) == "group:" then
|
||||||
groups[#groups + 1] = key:sub(7, #key)
|
-- build table with group recipe items while looping
|
||||||
|
grouped_ingredients[key] = key:sub(7):split(',')
|
||||||
else
|
else
|
||||||
|
-- if the item to consume doesn't exist in inventory
|
||||||
|
-- or not enough of them, abort crafting
|
||||||
if not inv_index[key] or inv_index[key] < count then
|
if not inv_index[key] or inv_index[key] < count then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@ -118,28 +126,45 @@ local function calculate_consumption(inv_index, consumption_with_groups)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- helper function to resolve matching ingredients with multiple group
|
||||||
|
-- requirements
|
||||||
|
local function ingredient_groups_match_item(ingredient_groups, name)
|
||||||
|
local found = 0
|
||||||
|
local count_ingredient_groups = #ingredient_groups
|
||||||
|
for i = 1, count_ingredient_groups do
|
||||||
|
if minetest.get_item_group(name,
|
||||||
|
ingredient_groups[i]) ~= 0
|
||||||
|
then
|
||||||
|
found = found + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return found == count_ingredient_groups
|
||||||
|
end
|
||||||
|
|
||||||
-- Next, resolve groups using the remaining items in the inventory
|
-- Next, resolve groups using the remaining items in the inventory
|
||||||
local take
|
if next(grouped_ingredients) ~= nil then
|
||||||
if #groups > 0 then
|
local take
|
||||||
for itemname, count in pairs(inv_index) do
|
for itemname, count in pairs(inv_index) do
|
||||||
if count > 0 then
|
if count > 0 then
|
||||||
local def = minetest.registered_items[itemname]
|
-- groupname is the string as defined by recipe.
|
||||||
local item_groups = def and def.groups or {}
|
-- e.g. group:dye,color_blue
|
||||||
for i = 1, #groups do
|
-- groups holds the group names split into a list
|
||||||
local group = groups[i]
|
-- ready to be passed to core.get_item_group()
|
||||||
local groupname = "group:" .. group
|
for groupname, groups in pairs(grouped_ingredients) do
|
||||||
if item_groups[group] and item_groups[group] >= 1
|
if consumption_with_groups[groupname] > 0
|
||||||
and consumption_with_groups[groupname] > 0
|
and ingredient_groups_match_item(groups, itemname)
|
||||||
then
|
then
|
||||||
take = math.min(count, consumption_with_groups[groupname])
|
take = math.min(count,
|
||||||
|
consumption_with_groups[groupname])
|
||||||
consumption_with_groups[groupname] =
|
consumption_with_groups[groupname] =
|
||||||
consumption_with_groups[groupname] - take
|
consumption_with_groups[groupname] - take
|
||||||
|
|
||||||
assert(consumption_with_groups[groupname] >= 0)
|
assert(consumption_with_groups[groupname] >= 0)
|
||||||
consumption[itemname] =
|
consumption[itemname] =
|
||||||
(consumption[itemname] or 0) + take
|
(consumption[itemname] or 0) + take
|
||||||
|
|
||||||
inv_index[itemname] = inv_index[itemname] - take
|
inv_index[itemname] =
|
||||||
|
inv_index[itemname] - take
|
||||||
assert(inv_index[itemname] >= 0)
|
assert(inv_index[itemname] >= 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user