forked from mtcontrib/pipeworks
remove unnecessary looping and testing, since we only check and update the cache if there was actually a reason to assume a recipe change
This commit is contained in:
parent
827d049789
commit
cee16932be
126
autocrafter.lua
126
autocrafter.lua
|
@ -1,11 +1,12 @@
|
||||||
local autocrafterCache = {} -- caches some recipe data to avoid to call the slow function minetest.get_craft_result() every second
|
local autocrafterCache = {} -- caches some recipe data to avoid to call the slow function minetest.get_craft_result() every second
|
||||||
|
|
||||||
local function make_inventory_cache(invlist)
|
local function count_index(invlist)
|
||||||
local l = {}
|
local index = {}
|
||||||
for _, stack in ipairs(invlist) do
|
for _, stack in ipairs(invlist) do
|
||||||
l[stack:get_name()] = (l[stack:get_name()] or 0) + stack:get_count()
|
local stack_name = stack:get_name()
|
||||||
|
index[stack_name] = (index[stack_name] or 0) + stack:get_count()
|
||||||
end
|
end
|
||||||
return l
|
return index
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_cached_craft(pos)
|
local function get_cached_craft(pos)
|
||||||
|
@ -13,71 +14,36 @@ local function get_cached_craft(pos)
|
||||||
return hash, autocrafterCache[hash]
|
return hash, autocrafterCache[hash]
|
||||||
end
|
end
|
||||||
|
|
||||||
local function autocraft(inventory, pos)
|
-- note, that this function assumes allready being updated to virtual items
|
||||||
|
-- and doesn't handle recipes with stacksizes > 1
|
||||||
|
local function on_recipe_change(pos, inventory)
|
||||||
if not inventory then return end
|
if not inventory then return end
|
||||||
local recipe = inventory:get_list("recipe")
|
local recipe = inventory:get_list("recipe")
|
||||||
if not recipe then return end
|
if not recipe then return end
|
||||||
local cached_recipe
|
|
||||||
local output
|
|
||||||
local decremented_input
|
|
||||||
|
|
||||||
local hash, craft = get_cached_craft(pos)
|
|
||||||
if craft == nil then
|
|
||||||
cached_recipe = {}
|
|
||||||
for i = 1, 9 do
|
|
||||||
cached_recipe[i] = recipe[i]
|
|
||||||
recipe[i] = ItemStack({name = recipe[i]:get_name(), count = 1})
|
|
||||||
end
|
|
||||||
output, decremented_input = minetest.get_craft_result({method = "normal", width = 3, items = recipe})
|
|
||||||
autocrafterCache[hash] = {recipe = recipe, output = output, decremented_input = decremented_input}
|
|
||||||
else
|
|
||||||
cached_recipe, output, decremented_input = craft.recipe, craft.output, craft.decremented_input
|
|
||||||
local recipe_changed = false
|
local recipe_changed = false
|
||||||
|
local hash, craft = get_cached_craft(pos)
|
||||||
|
|
||||||
|
if not craft then
|
||||||
|
recipe_changed = true
|
||||||
|
else
|
||||||
|
-- check if it changed
|
||||||
|
local cached_recipe = craft.recipe
|
||||||
for i = 1, 9 do
|
for i = 1, 9 do
|
||||||
local recipe_entry, cached_recipe_entry = recipe[i], cached_recipe[i]
|
if recipe[i]:get_name() ~= cached_recipe[i]:get_name() then
|
||||||
if recipe_entry:get_name() ~= cached_recipe_entry:get_name()
|
|
||||||
or recipe_entry:get_count() ~= cached_recipe_entry:get_count() then
|
|
||||||
recipe_changed = true
|
recipe_changed = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if recipe_changed then
|
|
||||||
for i = 1, 9 do
|
|
||||||
cached_recipe[i] = recipe[i]
|
|
||||||
recipe[i] = ItemStack({name = recipe[i]:get_name(), count = 1})
|
|
||||||
end
|
|
||||||
output, decremented_input = minetest.get_craft_result({method = "normal", width = 3, items = recipe})
|
|
||||||
autocrafterCache[hash] = {recipe = recipe, output = output, decremented_input = decremented_input}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if output.item:is_empty() then return end
|
if recipe_changed then
|
||||||
output = output.item
|
local output, decremented_input = minetest.get_craft_result({method = "normal", width = 3, items = recipe})
|
||||||
if not inventory:room_for_item("dst", output) then return end
|
craft = {recipe = recipe, output = output, decremented_input = decremented_input}
|
||||||
local to_use = {}
|
autocrafterCache[hash] = craft
|
||||||
for _, item in ipairs(recipe) do
|
|
||||||
if item~= nil and not item:is_empty() then
|
|
||||||
local item_name = item:get_name()
|
|
||||||
if to_use[item_name] == nil then
|
|
||||||
to_use[item_name] = 1
|
|
||||||
else
|
|
||||||
to_use[item_name] = to_use[item_name]+1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local invcache = make_inventory_cache(inventory:get_list("src"))
|
|
||||||
for itemname, number in pairs(to_use) do
|
|
||||||
if (not invcache[itemname]) or invcache[itemname] < number then return end
|
|
||||||
end
|
|
||||||
for itemname, number in pairs(to_use) do
|
|
||||||
for i = 1, number do -- We have to do that since remove_item does not work if count > stack_max
|
|
||||||
inventory:remove_item("src", ItemStack(itemname))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
inventory:add_item("dst", output)
|
|
||||||
for i = 1, 9 do
|
|
||||||
inventory:add_item("dst", decremented_input.items[i])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return craft
|
||||||
end
|
end
|
||||||
|
|
||||||
local function update_autocrafter(pos)
|
local function update_autocrafter(pos)
|
||||||
|
@ -91,6 +57,50 @@ local function update_autocrafter(pos)
|
||||||
stack:set_wear(0)
|
stack:set_wear(0)
|
||||||
inv:set_stack("recipe", idx, stack)
|
inv:set_stack("recipe", idx, stack)
|
||||||
end
|
end
|
||||||
|
on_recipe_change(pos, inv)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function autocraft(inventory, pos)
|
||||||
|
if not inventory then return end
|
||||||
|
local recipe = inventory:get_list("recipe")
|
||||||
|
if not recipe then return end
|
||||||
|
|
||||||
|
local hash, craft = get_cached_craft(pos)
|
||||||
|
if craft == nil then
|
||||||
|
update_autocrafter(pos) -- only does some unnecessary calls for "old" autocrafters
|
||||||
|
craft = on_recipe_change(pos, inventory)
|
||||||
|
end
|
||||||
|
|
||||||
|
local output_item = craft.output.item
|
||||||
|
if output_item:is_empty() or not inventory:room_for_item("dst", output_item) then return end
|
||||||
|
|
||||||
|
-- determine how much we have to consume each craft
|
||||||
|
local consumption = {}
|
||||||
|
for _, item in ipairs(recipe) do
|
||||||
|
if item and not item:is_empty() then
|
||||||
|
local item_name = item:get_name()
|
||||||
|
consumption[item_name] = (consumption[item_name] or 0) + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local inv_index = count_index(inventory:get_list("src"))
|
||||||
|
-- check if we have enough materials available
|
||||||
|
for itemname, number in pairs(consumption) do
|
||||||
|
if (not inv_index[itemname]) or inv_index[itemname] < number then return end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- consume materials
|
||||||
|
for itemname, number in pairs(consumption) do
|
||||||
|
for i = 1, number do -- We have to do that since remove_item does not work if count > stack_max
|
||||||
|
inventory:remove_item("src", ItemStack(itemname))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- craft the result into the dst inventory and add any "replacements" as well
|
||||||
|
inventory:add_item("dst", output_item)
|
||||||
|
for i = 1, 9 do
|
||||||
|
inventory:add_item("dst", craft.decremented_input.items[i])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -147,6 +157,7 @@ minetest.register_node("pipeworks:autocrafter", {
|
||||||
local stack_copy = ItemStack(stack)
|
local stack_copy = ItemStack(stack)
|
||||||
stack_copy:set_count(1)
|
stack_copy:set_count(1)
|
||||||
inv:set_stack(listname, index, stack_copy)
|
inv:set_stack(listname, index, stack_copy)
|
||||||
|
on_recipe_change(pos, inv)
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return stack:get_count()
|
return stack:get_count()
|
||||||
|
@ -157,6 +168,7 @@ minetest.register_node("pipeworks:autocrafter", {
|
||||||
local inv = minetest.get_meta(pos):get_inventory()
|
local inv = minetest.get_meta(pos):get_inventory()
|
||||||
if listname == "recipe" then
|
if listname == "recipe" then
|
||||||
inv:set_stack(listname, index, ItemStack(""))
|
inv:set_stack(listname, index, ItemStack(""))
|
||||||
|
on_recipe_change(pos, inv)
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return stack:get_count()
|
return stack:get_count()
|
||||||
|
@ -169,11 +181,13 @@ minetest.register_node("pipeworks:autocrafter", {
|
||||||
stack:set_count(count)
|
stack:set_count(count)
|
||||||
if from_list == "recipe" then
|
if from_list == "recipe" then
|
||||||
inv:set_stack(from_list, from_index, ItemStack(""))
|
inv:set_stack(from_list, from_index, ItemStack(""))
|
||||||
|
on_recipe_change(pos, inv)
|
||||||
return 0
|
return 0
|
||||||
elseif to_list == "recipe" then
|
elseif to_list == "recipe" then
|
||||||
local stack_copy = ItemStack(stack)
|
local stack_copy = ItemStack(stack)
|
||||||
stack_copy:set_count(1)
|
stack_copy:set_count(1)
|
||||||
inv:set_stack(to_list, to_index, stack_copy)
|
inv:set_stack(to_list, to_index, stack_copy)
|
||||||
|
on_recipe_change(pos, inv)
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return stack:get_count()
|
return stack:get_count()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user