group.lua 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. local S = unified_inventory.gettext
  2. function unified_inventory.canonical_item_spec_matcher(spec)
  3. local specname = ItemStack(spec):get_name()
  4. if specname:sub(1, 6) == "group:" then
  5. local group_names = specname:sub(7):split(",")
  6. return function (itemname)
  7. local itemdef = minetest.registered_items[itemname]
  8. for _, group_name in ipairs(group_names) do
  9. if (itemdef.groups[group_name] or 0) == 0 then
  10. return false
  11. end
  12. end
  13. return true
  14. end
  15. else
  16. return function (itemname) return itemname == specname end
  17. end
  18. end
  19. function unified_inventory.item_matches_spec(item, spec)
  20. local itemname = ItemStack(item):get_name()
  21. return unified_inventory.canonical_item_spec_matcher(spec)(itemname)
  22. end
  23. function unified_inventory.extract_groupnames(groupname)
  24. local specname = ItemStack(groupname):get_name()
  25. if specname:sub(1, 6) == "group:" then
  26. local group_names = specname:sub(7):split(",")
  27. if #group_names == 1 then
  28. return group_names[1], 1
  29. end
  30. local s = ""
  31. for g=1,#group_names do
  32. if g > 1 then
  33. -- List connector
  34. s = s .. S(" and ")
  35. end
  36. s = s .. group_names[g]
  37. end
  38. return s, #group_names
  39. else
  40. return nil, 0
  41. end
  42. end
  43. unified_inventory.registered_group_items = {
  44. mesecon_conductor_craftable = "mesecons:wire_00000000_off",
  45. stone = "default:cobble",
  46. wood = "default:wood",
  47. book = "default:book",
  48. sand = "default:sand",
  49. leaves = "default:leaves",
  50. tree = "default:tree",
  51. vessel = "vessels:glass_bottle",
  52. wool = "wool:white",
  53. }
  54. function unified_inventory.register_group_item(groupname, itemname)
  55. unified_inventory.registered_group_items[groupname] = itemname
  56. end
  57. -- This is used when displaying craft recipes, where an ingredient is
  58. -- specified by group rather than as a specific item. A single-item group
  59. -- is represented by that item, with the single-item status signalled
  60. -- in the "sole" field. If the group contains no items at all, the item
  61. -- field will be nil.
  62. --
  63. -- Within a multiple-item group, we prefer to use an item that has the
  64. -- same specific name as the group, and if there are more than one of
  65. -- those items we prefer the one registered for the group by a mod.
  66. -- Among equally-preferred items, we just pick the one with the
  67. -- lexicographically earliest name.
  68. --
  69. -- The parameter to this function isn't just a single group name.
  70. -- It may be a comma-separated list of group names. This is really a
  71. -- "group:..." ingredient specification, minus the "group:" prefix.
  72. local function compute_group_item(group_name_list)
  73. local group_names = group_name_list:split(",")
  74. local candidate_items = {}
  75. for itemname, itemdef in pairs(minetest.registered_items) do
  76. if (itemdef.groups.not_in_creative_inventory or 0) == 0 then
  77. local all = true
  78. for _, group_name in ipairs(group_names) do
  79. if (itemdef.groups[group_name] or 0) == 0 then
  80. all = false
  81. end
  82. end
  83. if all then table.insert(candidate_items, itemname) end
  84. end
  85. end
  86. local num_candidates = #candidate_items
  87. if num_candidates == 0 then
  88. return {sole = true}
  89. elseif num_candidates == 1 then
  90. return {item = candidate_items[1], sole = true}
  91. end
  92. local is_group = {}
  93. local registered_rep = {}
  94. for _, group_name in ipairs(group_names) do
  95. is_group[group_name] = true
  96. local rep = unified_inventory.registered_group_items[group_name]
  97. if rep then registered_rep[rep] = true end
  98. end
  99. local bestitem = ""
  100. local bestpref = 0
  101. for _, item in ipairs(candidate_items) do
  102. local pref
  103. if registered_rep[item] then
  104. pref = 4
  105. elseif string.sub(item, 1, 8) == "default:" and is_group[string.sub(item, 9)] then
  106. pref = 3
  107. elseif is_group[item:gsub("^[^:]*:", "")] then
  108. pref = 2
  109. else
  110. pref = 1
  111. end
  112. if pref > bestpref or (pref == bestpref and item < bestitem) then
  113. bestitem = item
  114. bestpref = pref
  115. end
  116. end
  117. return {item = bestitem, sole = false}
  118. end
  119. local group_item_cache = {}
  120. function unified_inventory.get_group_item(group_name)
  121. if not group_item_cache[group_name] then
  122. group_item_cache[group_name] = compute_group_item(group_name)
  123. end
  124. return group_item_cache[group_name]
  125. end