141 lines
3.6 KiB
Lua
141 lines
3.6 KiB
Lua
local add_or_create = function(t, i, n)
|
|
t[i] = t[i] and t[i] + n or n
|
|
end
|
|
|
|
local get_group_item = function(invCache, groups)
|
|
local maxCount = 0
|
|
local maxItem
|
|
local isInGroups
|
|
|
|
for item, count in pairs(invCache) do
|
|
isInGroups = true
|
|
|
|
for _, group in ipairs(groups) do
|
|
if minetest.get_item_group(item, group) == 0 then
|
|
isInGroups = false
|
|
break
|
|
end
|
|
end
|
|
|
|
if isInGroups and count > maxCount then
|
|
maxItem = item
|
|
maxCount = count
|
|
end
|
|
end
|
|
|
|
return maxItem
|
|
end
|
|
|
|
cg.auto_get_craftable = function(player, craft)
|
|
local inv = player:get_inventory():get_list("main")
|
|
local invCache = {}
|
|
|
|
-- Create a cache of the inventory with itemName = count pairs. This speeds up searching for items.
|
|
for _, stack in ipairs(inv) do
|
|
if stack:get_count() > 0 then
|
|
add_or_create(invCache, stack:get_name(), stack:get_count())
|
|
end
|
|
end
|
|
|
|
local reqItems = {}
|
|
local reqGroups = {}
|
|
|
|
-- Find out how many of each item/group is required to craft one item.
|
|
for _, item in pairs(craft.items) do
|
|
if item:sub(1, 6) == "group:" then
|
|
add_or_create(reqGroups, item, 1)
|
|
else
|
|
add_or_create(reqItems, item, 1)
|
|
end
|
|
end
|
|
|
|
local gMaxItem
|
|
|
|
-- For each group, find the item in that group from the player's inventory with the largest count.
|
|
for group, count in pairs(reqGroups) do
|
|
gMaxItem = get_group_item(invCache, group:sub(7):split(","))
|
|
|
|
if gMaxItem then
|
|
add_or_create(reqItems, gMaxItem, count)
|
|
else
|
|
return 0
|
|
end
|
|
end
|
|
|
|
local craftable = 1000
|
|
|
|
for item, count in pairs(reqItems) do
|
|
if invCache[item] then
|
|
craftable = math.min(craftable, math.floor(invCache[item] / count))
|
|
else
|
|
return 0
|
|
end
|
|
|
|
-- We can't craft more than the stack_max of our ingredients.
|
|
if minetest.registered_items[item].stack_max then
|
|
craftable = math.min(craftable, minetest.registered_items[item].stack_max)
|
|
end
|
|
end
|
|
|
|
return craftable
|
|
end
|
|
|
|
cg.auto_craft = function(player, craft, num)
|
|
inv = player:get_inventory()
|
|
|
|
if not inv:is_empty("craft") then
|
|
-- Attempt to move items to the player's main inventory.
|
|
for idx, stack in ipairs(inv:get_list("craft")) do
|
|
if not stack:is_empty() then
|
|
stack = inv:add_item("main", stack)
|
|
inv:set_stack("craft", idx, stack)
|
|
end
|
|
end
|
|
|
|
-- Check again, and return if not all items were moved.
|
|
if not inv:is_empty("craft") then
|
|
minetest.chat_send_player(player:get_player_name(), cg.S("Item could not be crafted!"))
|
|
return
|
|
end
|
|
end
|
|
|
|
if craft.width > inv:get_width("craft") or table.maxn(craft.items) > inv:get_size("craft") then return end
|
|
|
|
local width = craft.width == 0 and inv:get_width("craft") or craft.width
|
|
local stack, invCache
|
|
local groupCache = {}
|
|
|
|
for idx, item in pairs(craft.items) do
|
|
-- Shift the indices so the items in the craft go to the right spots on the crafting grid.
|
|
idx = idx + (inv:get_width("craft") - width) * math.floor((idx - 1) / width)
|
|
|
|
if item:sub(1, 6) == "group:" then
|
|
-- Create an inventory cache.
|
|
if not invCache then
|
|
invCache = {}
|
|
|
|
for _, stack in ipairs(inv:get_list("main")) do
|
|
if stack:get_count() > 0 then
|
|
add_or_create(invCache, stack:get_name(), stack:get_count())
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Get the most plentiful item in the group.
|
|
if not groupCache[item] then
|
|
groupCache[item] = get_group_item(invCache, item:sub(7):split(","))
|
|
end
|
|
|
|
-- Move the selected item.
|
|
if groupCache[item] then
|
|
stack = inv:remove_item("main", ItemStack({name = groupCache[item], count = num}))
|
|
inv:set_stack("craft", idx, stack)
|
|
end
|
|
else
|
|
-- Move the item.
|
|
stack = inv:remove_item("main", ItemStack({name = item, count = num}))
|
|
inv:set_stack("craft", idx, stack)
|
|
end
|
|
end
|
|
end
|