diff --git a/match_craft.lua b/match_craft.lua index 97cbfc7..046c3d5 100644 --- a/match_craft.lua +++ b/match_craft.lua @@ -4,144 +4,6 @@ local function extract_group_name(name) return name:match("^group:(.+)") end -local function add_craft_item(t, item_name, craft_pos) - local item = t[item_name] - - if item == nil then - t[item_name] = { - craft_positions = {craft_pos}, - found = false - } - else - table.insert(item.craft_positions, craft_pos) - end -end - -local function add_craft_group(t, group_name, craft_pos) - local group = t[group_name] - - if group == nil then - t[group_name] = { - craft_positions = {craft_pos}, - found = false, - found_items = {} - } - else - table.insert(group.craft_positions, craft_pos) - end -end - -local function create_craft_index(craft) - local craft_index = { - items = {}, - groups = {} - } - - local MAX_HEIGHT = 3 - local MAX_WIDTH = 3 - - local craft_items = craft.items - local craft_width = craft.width - - if craft_width == 0 then - craft_width = MAX_WIDTH - end - - local pos = 1 - - for y = 1, MAX_HEIGHT do - for x = 1, craft_width do - local craft_pos = (y - 1) * MAX_WIDTH + x - local item = craft_items[pos] - - if item ~= nil then - local group = extract_group_name(item) - - if group == nil then - add_craft_item(craft_index.items, item, craft_pos) - else - add_craft_group(craft_index.groups, group, craft_pos) - end - end - - pos = pos + 1 - end - end - - return craft_index -end - -local function find_craft_item(item_name, craft_index) - local found = false - local item = craft_index.items[item_name] - local get_item_group = minetest.get_item_group - - if item ~= nil then - item.found = true - found = true - end - - for group_name, group in pairs(craft_index.groups) do - if get_item_group(item_name, group_name) > 0 then - group.found = true - found = true - - table.insert(group.found_items, item_name) - end - end - - return found -end - -local function all_items_found(craft_index) - for _, item in pairs(craft_index.items) do - if not item.found then - return false - end - end - - for _, group in pairs(craft_index.groups) do - if not group.found then - return false - end - end - - return true -end - -local function create_item_index(inv_list, craft_index) - local item_index = {} - local not_found = {} - - for inv_list_pos, stack in ipairs(inv_list) do - local item_name = stack:get_name() - - if item_name ~= "" then - local item_count = stack:get_count() - local item = item_index[item_name] - - if item == nil then - if not_found[item_name] == nil then - local item_found = find_craft_item(item_name, craft_index) - - if item_found then - item_index[item_name] = { - total_count = item_count, - times_matched = 0 - } - else - not_found[item_name] = true - end - end - else - item.total_count = item.total_count + item_count - end - end - end - - return item_index -end - local function count_compare(item1, item2) return item1.index.total_count > item2.index.total_count end @@ -166,7 +28,145 @@ local function lex_compare(group1, group2) return len1 < len2 end -local function get_group_items(group_name, craft_index, item_index) +function unified_inventory.add_craft_item(t, item_name, craft_pos) + local item = t[item_name] + + if item == nil then + t[item_name] = { + craft_positions = {craft_pos}, + found = false + } + else + table.insert(item.craft_positions, craft_pos) + end +end + +function unified_inventory.add_craft_group(t, group_name, craft_pos) + local group = t[group_name] + + if group == nil then + t[group_name] = { + craft_positions = {craft_pos}, + found = false, + found_items = {} + } + else + table.insert(group.craft_positions, craft_pos) + end +end + +function unified_inventory.create_craft_index(craft) + local craft_index = { + items = {}, + groups = {} + } + + local MAX_HEIGHT = 3 + local MAX_WIDTH = 3 + + local craft_items = craft.items + local craft_width = craft.width + + if craft_width == 0 then + craft_width = MAX_WIDTH + end + + local pos = 1 + + for y = 1, MAX_HEIGHT do + for x = 1, craft_width do + local craft_pos = (y - 1) * MAX_WIDTH + x + local item = craft_items[pos] + + if item ~= nil then + local group = extract_group_name(item) + + if group == nil then + unified_inventory.add_craft_item(craft_index.items, item, craft_pos) + else + unified_inventory.add_craft_group(craft_index.groups, group, craft_pos) + end + end + + pos = pos + 1 + end + end + + return craft_index +end + +function unified_inventory.find_craft_item(item_name, craft_index) + local found = false + local item = craft_index.items[item_name] + local get_item_group = minetest.get_item_group + + if item ~= nil then + item.found = true + found = true + end + + for group_name, group in pairs(craft_index.groups) do + if get_item_group(item_name, group_name) > 0 then + group.found = true + found = true + + table.insert(group.found_items, item_name) + end + end + + return found +end + +function unified_inventory.all_items_found(craft_index) + for _, item in pairs(craft_index.items) do + if not item.found then + return false + end + end + + for _, group in pairs(craft_index.groups) do + if not group.found then + return false + end + end + + return true +end + +function unified_inventory.create_item_index(inv_list, craft_index) + local item_index = {} + local not_found = {} + + for inv_list_pos, stack in ipairs(inv_list) do + local item_name = stack:get_name() + + if item_name ~= "" then + local item_count = stack:get_count() + local item = item_index[item_name] + + if item == nil then + if not_found[item_name] == nil then + local item_found = unified_inventory.find_craft_item(item_name, craft_index) + + if item_found then + item_index[item_name] = { + total_count = item_count, + times_matched = 0 + } + else + not_found[item_name] = true + end + end + else + item.total_count = item.total_count + item_count + end + end + end + + return item_index +end + +function unified_inventory.get_group_items(group_name, craft_index, item_index) local items = {} local group = craft_index.groups[group_name] @@ -182,11 +182,11 @@ local function get_group_items(group_name, craft_index, item_index) return items end -local function ordered_groups(craft_index, item_index) +function unified_inventory.ordered_groups(craft_index, item_index) local groups = {} for group_name in pairs(craft_index.groups) do - local group_items = get_group_items(group_name, craft_index, item_index) + local group_items = unified_inventory.get_group_items(group_name, craft_index, item_index) table.sort(group_items, count_compare) table.insert(groups, { @@ -210,7 +210,7 @@ local function ordered_groups(craft_index, item_index) end end -local function match_items(m, craft_index, item_index) +function unified_inventory.match_items(m, craft_index, item_index) for item_name, item in pairs(craft_index.items) do local index = item_index[item_name] local times_used = #item.craft_positions @@ -225,8 +225,8 @@ local function match_items(m, craft_index, item_index) end end -local function match_groups(m, craft_index, item_index) - for group, group_items in ordered_groups(craft_index, item_index) do +function unified_inventory.match_groups(m, craft_index, item_index) + for group, group_items in unified_inventory.ordered_groups(craft_index, item_index) do for _, craft_pos in ipairs(group.craft_positions) do local cell_count = 0 local matched_item = nil @@ -253,30 +253,30 @@ local function match_groups(m, craft_index, item_index) end end -local function get_match_table(craft_index, item_index) +function unified_inventory.get_match_table(craft_index, item_index) local match_table = { count = MAX_COUNT, items = {} } - match_items(match_table, craft_index, item_index) - match_groups(match_table, craft_index, item_index) + unified_inventory.match_items(match_table, craft_index, item_index) + unified_inventory.match_groups(match_table, craft_index, item_index) return match_table end -local function find_best_match(inv_list, craft) - local craft_index = create_craft_index(craft) - local item_index = create_item_index(inv_list, craft_index) +function unified_inventory.find_best_match(inv_list, craft) + local craft_index = unified_inventory.create_craft_index(craft) + local item_index = unified_inventory.create_item_index(inv_list, craft_index) - if not all_items_found(craft_index) then + if not unified_inventory.all_items_found(craft_index) then return end - return get_match_table(craft_index, item_index) + return unified_inventory.get_match_table(craft_index, item_index) end -local function can_move(match_items, inv_list) +function unified_inventory.can_move(match_items, inv_list) for match_pos, match_name in pairs(match_items) do local inv_item = inv_list[match_pos] local inv_item_name = inv_item:get_name() @@ -293,7 +293,7 @@ function unified_inventory.craftguide_match_craft(inv, src_list_name, dst_list_n local src_list = inv:get_list(src_list_name) local dst_list = inv:get_list(dst_list_name) - local craft_match = find_best_match(src_list, craft) + local craft_match = unified_inventory.find_best_match(src_list, craft) if craft_match == nil then return @@ -302,7 +302,7 @@ function unified_inventory.craftguide_match_craft(inv, src_list_name, dst_list_n local matched_items = craft_match.items local matched_count = craft_match.count - if not can_move(matched_items, dst_list) then + if not unified_inventory.can_move(matched_items, dst_list) then return end