mirror of
				https://github.com/minetest-mods/unified_inventory.git
				synced 2025-11-04 09:25:31 +01:00 
			
		
		
		
	Improve group matching for 'copy to craft'
This commit is contained in:
		
							
								
								
									
										40
									
								
								api.lua
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								api.lua
									
									
									
									
									
								
							@@ -146,46 +146,10 @@ minetest.after(0.01, function()
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	-- Step 1: group-indexed lookup table for items
 | 
			
		||||
	local spec_matcher = {}
 | 
			
		||||
	for _, name in ipairs(ui.items_list) do
 | 
			
		||||
		-- we only need to care about groups, exact items are handled separately
 | 
			
		||||
		for group, value in pairs(minetest.registered_items[name].groups) do
 | 
			
		||||
			if value and value ~= 0 then
 | 
			
		||||
				if not spec_matcher[group] then
 | 
			
		||||
					spec_matcher[group] = {}
 | 
			
		||||
				end
 | 
			
		||||
				spec_matcher[group][name] = true
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	unified_inventory.init_matching_cache()
 | 
			
		||||
 | 
			
		||||
	-- Step 2: Find all matching items for the given spec (groups)
 | 
			
		||||
	local function get_matching_spec_items(specname)
 | 
			
		||||
		if specname:sub(1,6) ~= "group:" then
 | 
			
		||||
			return { [specname] = true }
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		local accepted = {}
 | 
			
		||||
		for i, group in ipairs(specname:sub(7):split(",")) do
 | 
			
		||||
			if i == 1 then
 | 
			
		||||
				-- First step: Copy all possible item names in this group
 | 
			
		||||
				for name, _ in pairs(spec_matcher[group] or {}) do
 | 
			
		||||
					accepted[name] = true
 | 
			
		||||
				end
 | 
			
		||||
			else
 | 
			
		||||
				-- Perform filtering
 | 
			
		||||
				if spec_matcher[group] then
 | 
			
		||||
					for name, _ in pairs(accepted) do
 | 
			
		||||
						accepted[name] = spec_matcher[group][name]
 | 
			
		||||
					end
 | 
			
		||||
				else
 | 
			
		||||
					-- No matching items
 | 
			
		||||
					return {}
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		return accepted
 | 
			
		||||
	end
 | 
			
		||||
	local get_matching_spec_items = unified_inventory.get_matching_items
 | 
			
		||||
 | 
			
		||||
	for _, recipes in pairs(ui.crafts_for.recipe) do
 | 
			
		||||
		-- List of crafts that return this item string (variable "_")
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										60
									
								
								group.lua
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								group.lua
									
									
									
									
									
								
							@@ -1,4 +1,5 @@
 | 
			
		||||
local S = minetest.get_translator("unified_inventory")
 | 
			
		||||
local ui = unified_inventory
 | 
			
		||||
 | 
			
		||||
function unified_inventory.extract_groupnames(groupname)
 | 
			
		||||
	local specname = ItemStack(groupname):get_name()
 | 
			
		||||
@@ -26,6 +27,7 @@ end
 | 
			
		||||
-- It may be a comma-separated list of group names.  This is really a
 | 
			
		||||
-- "group:..." ingredient specification, minus the "group:" prefix.
 | 
			
		||||
 | 
			
		||||
-- TODO Replace this with the more efficient spec matcher (below)
 | 
			
		||||
local function compute_group_item(group_name_list)
 | 
			
		||||
	local group_names = group_name_list:split(",")
 | 
			
		||||
	local candidate_items = {}
 | 
			
		||||
@@ -84,3 +86,61 @@ function unified_inventory.get_group_item(group_name)
 | 
			
		||||
	return group_item_cache[group_name]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
--[[
 | 
			
		||||
This is for filtering known items by groups
 | 
			
		||||
e.g. find all items that match "group:flower,yellow" (flower AND yellow groups)
 | 
			
		||||
]]
 | 
			
		||||
local spec_matcher = {}
 | 
			
		||||
function unified_inventory.init_matching_cache()
 | 
			
		||||
	for _, name in ipairs(ui.items_list) do
 | 
			
		||||
		-- we only need to care about groups, exact items are handled separately
 | 
			
		||||
		for group, value in pairs(minetest.registered_items[name].groups) do
 | 
			
		||||
			if value and value ~= 0 then
 | 
			
		||||
				if not spec_matcher[group] then
 | 
			
		||||
					spec_matcher[group] = {}
 | 
			
		||||
				end
 | 
			
		||||
				spec_matcher[group][name] = true
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--[[
 | 
			
		||||
Retrieves all matching items
 | 
			
		||||
 | 
			
		||||
Arguments:
 | 
			
		||||
	specname (string): Item name or group(s) to filter
 | 
			
		||||
 | 
			
		||||
Output:
 | 
			
		||||
	{
 | 
			
		||||
		matchingitem1 = true,
 | 
			
		||||
		...
 | 
			
		||||
	}
 | 
			
		||||
]]
 | 
			
		||||
function unified_inventory.get_matching_items(specname)
 | 
			
		||||
	if specname:sub(1,6) ~= "group:" then
 | 
			
		||||
		return { [specname] = true }
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local accepted = {}
 | 
			
		||||
	for i, group in ipairs(specname:sub(7):split(",")) do
 | 
			
		||||
		if i == 1 then
 | 
			
		||||
			-- First step: Copy all possible item names in this group
 | 
			
		||||
			for name, _ in pairs(spec_matcher[group] or {}) do
 | 
			
		||||
				accepted[name] = true
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			-- Perform filtering
 | 
			
		||||
			if spec_matcher[group] then
 | 
			
		||||
				for name, _ in pairs(accepted) do
 | 
			
		||||
					accepted[name] = spec_matcher[group][name]
 | 
			
		||||
				end
 | 
			
		||||
			else
 | 
			
		||||
				-- No matching items
 | 
			
		||||
				return {}
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return accepted
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -126,25 +126,18 @@ Example output:
 | 
			
		||||
	}
 | 
			
		||||
--]]
 | 
			
		||||
function unified_inventory.find_usable_items(inv_items, craft_items)
 | 
			
		||||
	local get_group = minetest.get_item_group
 | 
			
		||||
	local result = {}
 | 
			
		||||
 | 
			
		||||
	for craft_item in pairs(craft_items) do
 | 
			
		||||
		local group = craft_item:match("^group:(.+)")
 | 
			
		||||
		local found = {}
 | 
			
		||||
		-- may specify group:type1,type2
 | 
			
		||||
		local items = unified_inventory.get_matching_items(craft_item)
 | 
			
		||||
 | 
			
		||||
		if group ~= nil then
 | 
			
		||||
			for inv_item in pairs(inv_items) do
 | 
			
		||||
				if get_group(inv_item, group) > 0 then
 | 
			
		||||
					found[inv_item] = true
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			if inv_items[craft_item] ~= nil then
 | 
			
		||||
				found[craft_item] = true
 | 
			
		||||
		local found = {}
 | 
			
		||||
		for itemname, _ in pairs(items) do
 | 
			
		||||
			if inv_items[itemname] then
 | 
			
		||||
				found[itemname] = true
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		result[craft_item] = found
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user