write something there
This commit is contained in:
commit
b4b6c08f4f
8546 changed files with 309825 additions and 0 deletions
146
mods/unified_inventory/group.lua
Normal file
146
mods/unified_inventory/group.lua
Normal file
|
@ -0,0 +1,146 @@
|
|||
local S = minetest.get_translator("unified_inventory")
|
||||
local ui = unified_inventory
|
||||
|
||||
function unified_inventory.extract_groupnames(groupname)
|
||||
local specname = ItemStack(groupname):get_name()
|
||||
if specname:sub(1, 6) ~= "group:" then
|
||||
return nil, 0
|
||||
end
|
||||
local group_names = specname:sub(7):split(",")
|
||||
return table.concat(group_names, S(" and ")), #group_names
|
||||
end
|
||||
|
||||
|
||||
-- This is used when displaying craft recipes, where an ingredient is
|
||||
-- specified by group rather than as a specific item. A single-item group
|
||||
-- is represented by that item, with the single-item status signalled
|
||||
-- in the "sole" field. If the group contains no items at all, the item
|
||||
-- field will be nil.
|
||||
--
|
||||
-- Within a multiple-item group, we prefer to use an item that has the
|
||||
-- same specific name as the group, and if there are more than one of
|
||||
-- those items we prefer the one registered for the group by a mod.
|
||||
-- Among equally-preferred items, we just pick the one with the
|
||||
-- lexicographically earliest name.
|
||||
--
|
||||
-- The parameter to this function isn't just a single group name.
|
||||
-- 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 = {}
|
||||
for itemname, itemdef in pairs(minetest.registered_items) do
|
||||
if (itemdef.groups.not_in_creative_inventory or 0) == 0 then
|
||||
local all = true
|
||||
for _, group_name in ipairs(group_names) do
|
||||
if (itemdef.groups[group_name] or 0) == 0 then
|
||||
all = false
|
||||
end
|
||||
end
|
||||
if all then table.insert(candidate_items, itemname) end
|
||||
end
|
||||
end
|
||||
local num_candidates = #candidate_items
|
||||
if num_candidates == 0 then
|
||||
return {sole = true}
|
||||
elseif num_candidates == 1 then
|
||||
return {item = candidate_items[1], sole = true}
|
||||
end
|
||||
local is_group = {}
|
||||
local registered_rep = {}
|
||||
for _, group_name in ipairs(group_names) do
|
||||
is_group[group_name] = true
|
||||
local rep = unified_inventory.registered_group_items[group_name]
|
||||
if rep then registered_rep[rep] = true end
|
||||
end
|
||||
local bestitem = ""
|
||||
local bestpref = 0
|
||||
for _, item in ipairs(candidate_items) do
|
||||
local pref
|
||||
if registered_rep[item] then
|
||||
pref = 4
|
||||
elseif string.sub(item, 1, 8) == "default:" and is_group[string.sub(item, 9)] then
|
||||
pref = 3
|
||||
elseif is_group[item:gsub("^[^:]*:", "")] then
|
||||
pref = 2
|
||||
else
|
||||
pref = 1
|
||||
end
|
||||
if pref > bestpref or (pref == bestpref and item < bestitem) then
|
||||
bestitem = item
|
||||
bestpref = pref
|
||||
end
|
||||
end
|
||||
return {item = bestitem, sole = false}
|
||||
end
|
||||
|
||||
|
||||
local group_item_cache = {}
|
||||
|
||||
function unified_inventory.get_group_item(group_name)
|
||||
if not group_item_cache[group_name] then
|
||||
group_item_cache[group_name] = compute_group_item(group_name)
|
||||
end
|
||||
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
|
Loading…
Add table
Add a link
Reference in a new issue