11 Commits

Author SHA1 Message Date
88b3033477 Purge recipes with invalid ingredients 2023-01-04 11:43:21 +01:00
19e14aa21e Improve group matching for 'copy to craft' 2023-01-04 11:43:15 +01:00
82cdf24045 Improve scroll height calculation (#220) 2022-12-30 21:43:46 +01:00
31c35dcd59 Remove dependency on farming (#219)
Avoids circular dependencies of 3rd party mods with unified_inventory -> farming -> stairs.
2022-12-12 17:45:53 +01:00
826d5f4683 Add setting to hide disabled buttons (#217) 2022-10-26 10:05:03 +02:00
db1c3c10b8 API doc: use Minetest style 2022-10-05 21:07:41 +02:00
9533200e25 Tidy and comment filtering functions 2022-10-05 21:07:11 +02:00
177debd13c Bags: Disallow moving bags into themselves
Previously, the bag and its list would disappear immediately.
2022-09-15 12:53:41 +02:00
8e9ea34ae8 Elaborate the use of NS() 2022-09-15 10:56:01 +02:00
574de91971 Craft guide: Add support for colored items (#213) 2022-09-15 10:48:29 +02:00
fc562ecaa0 Update German translation (#211)
Added categories, waypoint etc. translations updated, inventory trashing button still missing
2022-09-04 18:35:00 +02:00
12 changed files with 269 additions and 208 deletions

137
api.lua
View File

@ -2,40 +2,49 @@ local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape
local ui = unified_inventory
local function is_recipe_craftable(recipe)
-- Ensure the ingedients exist
for _, itemname in pairs(recipe.items) do
local groups = string.find(itemname, "group:")
if groups then
if not ui.get_group_item(string.sub(groups, 8)).item then
return false
end
else
-- Possibly an item
if not minetest.registered_items[itemname]
or minetest.get_item_group(itemname, "not_in_craft_guide") ~= 0 then
return false
end
end
end
return true
end
-- Create detached creative inventory after loading all mods
minetest.after(0.01, function()
local rev_aliases = {}
for source, target in pairs(minetest.registered_aliases) do
if not rev_aliases[target] then rev_aliases[target] = {} end
table.insert(rev_aliases[target], source)
for original, newname in pairs(minetest.registered_aliases) do
if not rev_aliases[newname] then
rev_aliases[newname] = {}
end
table.insert(rev_aliases[newname], original)
end
-- Filtered item list
ui.items_list = {}
for name, def in pairs(minetest.registered_items) do
if (not def.groups.not_in_creative_inventory or
def.groups.not_in_creative_inventory == 0) and
def.description and def.description ~= "" then
if ui.is_itemdef_listable(def) then
table.insert(ui.items_list, name)
-- Alias processing: Find recipes that belong to the current item name
local all_names = rev_aliases[name] or {}
table.insert(all_names, name)
for _, player_name in ipairs(all_names) do
local recipes = minetest.get_all_craft_recipes(player_name)
if recipes then
for _, recipe in ipairs(recipes) do
local unknowns
for _,chk in pairs(recipe.items) do
local groupchk = string.find(chk, "group:")
if (not groupchk and not minetest.registered_items[chk])
or (groupchk and not ui.get_group_item(string.gsub(chk, "group:", "")).item)
or minetest.get_item_group(chk, "not_in_craft_guide") ~= 0 then
unknowns = true
end
end
if not unknowns then
ui.register_craft(recipe)
end
for _, itemname in ipairs(all_names) do
local recipes = minetest.get_all_craft_recipes(itemname)
for _, recipe in ipairs(recipes or {}) do
if is_recipe_craftable(recipe) then
ui.register_craft(recipe)
end
end
end
@ -44,6 +53,8 @@ minetest.after(0.01, function()
table.sort(ui.items_list)
ui.items_list_size = #ui.items_list
print("Unified Inventory. Inventory size: "..ui.items_list_size)
-- Analyse dropped items -> custom "digging" recipes
for _, name in ipairs(ui.items_list) do
local def = minetest.registered_items[name]
-- Simple drops
@ -134,50 +145,18 @@ minetest.after(0.01, function()
end
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
-- Step 1: Initialize cache for looking up groups
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 get_matching_spec_items = unified_inventory.get_matching_items
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
for _, recipes in pairs(ui.crafts_for.recipe) do
for outputitemname, recipes in pairs(ui.crafts_for.recipe) do
-- List of crafts that return this item string (variable "_")
-- Problem: The group cache must be initialized after all mods finished loading
-- thus, invalid recipes might be indexed. Hence perform filtering with `new_recipe_list`
local new_recipe_list = {}
for _, recipe in ipairs(recipes) do
local ingredient_items = {}
for _, spec in pairs(recipe.items) do
@ -193,7 +172,14 @@ minetest.after(0.01, function()
end
table.insert(ui.crafts_for.usage[name], recipe)
end
if next(ingredient_items) then
-- There's at least one known ingredient: mark as good recipe
-- PS: What whatll be done about partially incomplete recipes?
table.insert(new_recipe_list, recipe)
end
end
ui.crafts_for.recipe[outputitemname] = new_recipe_list
end
for _, callback in ipairs(ui.initialized_callbacks) do
@ -201,8 +187,8 @@ minetest.after(0.01, function()
end
end)
---------------- Home API ----------------
-- load_home
local function load_home()
local input = io.open(ui.home_filename, "r")
if not input then
@ -219,6 +205,7 @@ local function load_home()
end
io.close(input)
end
load_home()
function ui.set_home(player, pos)
@ -247,7 +234,8 @@ function ui.go_home(player)
return false
end
-- register_craft
---------------- Crafting API ----------------
function ui.register_craft(options)
if not options.output then
return
@ -270,14 +258,12 @@ function ui.register_craft(options)
end
end
local craft_type_defaults = {
width = 3,
height = 3,
uses_crafting_grid = false,
}
function ui.craft_type_defaults(name, options)
if not options.description then
options.description = name
@ -288,8 +274,7 @@ end
function ui.register_craft_type(name, options)
ui.registered_craft_types[name] =
ui.craft_type_defaults(name, options)
ui.registered_craft_types[name] = ui.craft_type_defaults(name, options)
end
@ -346,6 +331,8 @@ ui.register_craft_type("digging_chance", {
height = 1,
})
---------------- GUI registrations ----------------
function ui.register_page(name, def)
ui.pages[name] = def
end
@ -361,6 +348,8 @@ function ui.register_button(name, def)
table.insert(ui.buttons, def)
end
---------------- Callback registrations ----------------
function ui.register_on_initialized(callback)
if type(callback) ~= "function" then
error(("Initialized callback must be a function, %s given."):format(type(callback)))
@ -375,6 +364,8 @@ function ui.register_on_craft_registered(callback)
table.insert(ui.craft_registered_callbacks, callback)
end
---------------- List getters ----------------
function ui.get_recipe_list(output)
return ui.crafts_for.recipe[output]
end
@ -387,11 +378,15 @@ function ui.get_registered_outputs()
return outputs
end
---------------- Player utilities ----------------
function ui.is_creative(playername)
return minetest.check_player_privs(playername, {creative=true})
or minetest.settings:get_bool("creative_mode")
end
---------------- Formspec helpers ----------------
function ui.single_slot(xpos, ypos, bright)
return string.format("background9[%f,%f;%f,%f;ui_single_slot%s.png;false;16]",
xpos, ypos, ui.imgscale, ui.imgscale, (bright and "_bright" or "") )

View File

@ -114,6 +114,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
end)
-- Player slots are preserved when unified_inventory is disabled. Do not allow modification.
-- Fix: use a detached inventory and store the data separately.
local function save_bags_metadata(player, bags_inv)
local is_empty = true
local bags = {}
@ -163,7 +165,7 @@ local function load_bags_metadata(player, bags_inv)
save_bags_metadata(player, bags_inv)
end
-- Clean up deprecated garbage after saving
-- Legacy: Clean up old player lists
for i = 1, 4 do
local bag = "bag" .. i
player_inv:set_size(bag, 0)
@ -172,46 +174,29 @@ end
minetest.register_on_joinplayer(function(player)
local player_name = player:get_player_name()
local bags_inv = minetest.create_detached_inventory(player_name .. "_bags",{
local bags_inv = minetest.create_detached_inventory(player_name .. "_bags", {
allow_put = function(inv, listname, index, stack, player)
local new_slots = stack:get_definition().groups.bagslots
if not new_slots then
return 0 -- ItemStack is not a bag.
end
-- The execution order of `allow_put`/`allow_take` is not defined.
-- We do not know the replacement ItemStack if the items are swapped.
-- Hence, bag slot upgrades and downgrades are not possible with the
-- current API.
if not player:get_inventory():is_empty(listname .. "contents") then
-- Legacy: in case `allow_take` is not executed on old Minetest versions.
return 0
end
return 1
end,
on_put = function(inv, listname, index, stack, player)
player:get_inventory():set_size(listname .. "contents",
stack:get_definition().groups.bagslots)
save_bags_metadata(player, inv)
end,
allow_put = function(inv, listname, index, stack, player)
local new_slots = stack:get_definition().groups.bagslots
if not new_slots then
return 0
end
local player_inv = player:get_inventory()
local old_slots = player_inv:get_size(listname .. "contents")
if new_slots >= old_slots then
return 1
end
-- using a smaller bag, make sure it fits
local old_list = player_inv:get_list(listname .. "contents")
local new_list = {}
local slots_used = 0
local use_new_list = false
for i, v in ipairs(old_list) do
if v and not v:is_empty() then
slots_used = slots_used + 1
use_new_list = i > new_slots
new_list[slots_used] = v
end
end
if new_slots >= slots_used then
if use_new_list then
player_inv:set_list(listname .. "contents", new_list)
end
return 1
end
-- New bag is smaller: Disallow inserting
return 0
end,
allow_take = function(inv, listname, index, stack, player)
if player:get_inventory():is_empty(listname .. "contents") then
return stack:get_count()
@ -230,6 +215,20 @@ minetest.register_on_joinplayer(function(player)
load_bags_metadata(player, bags_inv)
end)
minetest.register_allow_player_inventory_action(function(player, action, inventory, info)
-- From detached inventory -> player inventory: put & take callbacks
if action ~= "put" or not info.listname:find("bag%dcontents") then
return
end
if info.stack:get_definition().groups.bagslots then
-- Problem 1: empty bags could be moved into their own slots
-- Problem 2: cannot reliably keep track of ItemStack ownership due to
--> Disallow all external bag movements into this list
return 0
end
end)
-- register bag tools
minetest.register_tool("unified_inventory:bag_small", {
description = S("Small Bag"),

View File

@ -96,6 +96,9 @@ function unified_inventory.register_category(category_name, config)
end
update_category_list()
end
-- TODO: Mark these for removal. They are pretty much useless
function unified_inventory.set_category_symbol(category_name, symbol)
ensure_category_exists(category_name)
unified_inventory.registered_categories[category_name].symbol = symbol

View File

@ -1,7 +1,8 @@
unified_inventory API
=====================
This file provides information about the API of unified_inventory.
This file provides information about the API of unified_inventory
and can be viewed in Markdown readers.
API revisions within unified_inventory can be checked using:
@ -23,7 +24,9 @@ Grouped by use-case, afterwards sorted alphabetically.
Callbacks
---------
Register a callback that will be run whenever a craft is registered via unified_inventory.register_craft:
Register a callback that will be run whenever a craft is registered via unified_inventory.register_craft.
This callback is run before any recipe ingredients checks, hence it is also executed on recipes that are
purged after all mods finished loading.
unified_inventory.register_on_craft_registered(
function (item_name, options)
@ -163,68 +166,57 @@ Register a non-standard craft recipe:
Categories
----------
Register a new category:
The config table (second argument) is optional, and all its members are optional
See the unified_inventory.set_category_* functions for more details on the members of the config table
* `unified_inventory.register_category(name, def)`
* Registers a new category
* `name` (string): internal category name
* `def` (optional, table): also its fields are optional
unified_inventory.register_category("category_name", {
symbol = "mod_name:item_name" or "texture.png",
symbol = source,
-- ^ Can be in the format "mod_name:item_name" or "texture.png",
label = "Human Readable Label",
index = 5,
-- ^ Categories are sorted by index. Lower numbers appear before higher ones.
-- By default, the name is translated to a number: AA -> 0.0101, ZZ -> 0.2626
--- Predefined category indices: "all" = -2, "uncategorized" = -1
items = {
"mod_name:item_name",
"another_mod:different_item"
}
-- ^ List of items within this category
})
* `unified_inventory.remove_category(name)`
* Removes an entire category
Add / override the symbol for a category:
The category does not need to exist first
The symbol can be an item name or a texture image
If unset this will default to "default:stick"
Modifier functions (to be removed)
unified_inventory.set_category_symbol("category_name", "mod_name:item_name" or "texture.png")
* `unified_inventory.set_category_symbol(name, source)`
* Changes the symbol of the category. The category does not need to exist yet.
* `name` (string): internal category name
* `source` (string, optional): `"mod_name:item_name"` or `"texture.png"`.
Defaults to `"default:stick"` if not specified.
* `unified_inventory.set_category_label(name, label)`
* Changes the human readable label of the category.
* `name` (string): internal category name
* `label` (string): human readable label. Defaults to the category name.
* `unified_inventory.set_category_index(name, index)`
* Changes the sorting index of the category.
* `name` (string): internal category name
* `index` (numeric): any real number
Add / override the human readable label for a category:
If unset this will default to the category name
Item management
unified_inventory.set_category_label("category_name", "Human Readable Label")
* ` unified_inventory.add_category_item(name, itemname)`
* Adds a single item to the category
* `itemname` (string): self-explanatory
* `unified_inventory.add_category_items(name, { itemname1, itemname2, ... }`
* Same as above but with multiple items
* `unified_inventory.remove_category_item(name, itemname)`
* Removes an item from the category
* `unified_inventory.find_category(itemname)`
* Looks up the first category containing this item
* Returns: category name (string) or nil
* `unified_inventory.find_categories(itemname)`
* Looks up the item name within all registered categories
* Returns: array of category names (table)
Add / override the sorting index of the category:
Must be a number, can also be negative (-5) or fractional (2.345)
This determines the position the category appears in the list of categories
The "all" meta-category has index -2, the "misc"/"uncategorized" meta-category has index -1, use a negative number smaller than these to make a category appear before these in the list
By default categories are sorted alphabetically with an index between 0.0101(AA) and 0.2626(ZZ)
unified_inventory.set_category_index("category_name", 5)
Add a single item to a category:
unified_inventory.add_category_item("category_name", "mod_name:item_name")
Add multiple items to a category:
unified_inventory.add_category_items("category_name", {
"mod_name:item_name",
"another_mod:different_item"
})
Remove an item from a category:
unified_inventory.remove_category_item("category_name", "mod_name:item_name")
Remove a category entirely:
unified_inventory.remove_category("category_name")
Finding existing items in categories:
This will find the first category an item exists in
It should be used for checking if an item is catgorised
Returns "category_name" or nil
unified_inventory.find_category("mod_name:item_name")
This will find all the categories an item exists in
Returns a number indexed table (list) of category names
unified_inventory.find_categories("mod_name:item_name")

View File

@ -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

View File

@ -52,6 +52,8 @@ unified_inventory = {
list_img_offset = 0.13,
standard_background = "bgcolor[#0000]background9[0,0;1,1;ui_formbg_9_sliced.png;true;16]",
hide_disabled_buttons = minetest.settings:get_bool("unified_inventory_hide_disabled_buttons", false),
version = 4
}

View File

@ -52,9 +52,11 @@ local function formspec_tab_buttons(player, formspec, style)
local filtered_inv_buttons = {}
for i, def in pairs(ui.buttons) do
for _, def in pairs(ui.buttons) do
if not (style.is_lite_mode and def.hide_lite) then
table.insert(filtered_inv_buttons, def)
if def.condition == nil or def.condition(player) or not ui.hide_disabled_buttons then
table.insert(filtered_inv_buttons, def)
end
end
end
@ -71,13 +73,14 @@ local function formspec_tab_buttons(player, formspec, style)
local pos_y = math.floor((i - 1) / style.main_button_cols) * style.btn_spc
if def.type == "image" then
if (def.condition == nil or def.condition(player) == true) then
if (def.condition == nil or def.condition(player)) then
formspec[n] = string.format("image_button[%g,%g;%g,%g;%s;%s;]",
pos_x, pos_y, style.btn_size, style.btn_size,
F(def.image),
F(def.name))
formspec[n+1] = "tooltip["..F(def.name)..";"..(def.tooltip or "").."]"
n = n+2
else
formspec[n] = string.format("image[%g,%g;%g,%g;%s^[colorize:#808080:alpha]",
pos_x, pos_y, style.btn_size, style.btn_size,
@ -88,9 +91,10 @@ local function formspec_tab_buttons(player, formspec, style)
end
formspec[n] = "scroll_container_end[]"
if needs_scrollbar then
local total_rows = math.ceil(#filtered_inv_buttons / style.main_button_cols)
formspec[n+1] = ("scrollbaroptions[max=%i;arrows=hide]"):format(
-- This calculation is not 100% accurate but "good enough"
math.ceil((#filtered_inv_buttons - 1) / style.main_button_cols) * style.btn_spc * 5
(total_rows - style.main_button_rows) * style.btn_spc * 10
)
formspec[n+2] = ("scrollbar[%g,%g;0.4,%g;vertical;tabbtnscroll;0]"):format(
style.main_button_x + style.main_button_cols * style.btn_spc - 0.1, -- x pos
@ -329,7 +333,7 @@ function ui.set_inventory_formspec(player, page)
end
end
local function valid_def(def)
function ui.is_itemdef_listable(def)
return (not def.groups.not_in_creative_inventory
or def.groups.not_in_creative_inventory == 0)
and def.description
@ -342,9 +346,11 @@ function ui.apply_filter(player, filter, search_dir)
return false
end
local player_name = player:get_player_name()
local lfilter = string.lower(filter)
local ffilter
if lfilter:sub(1, 6) == "group:" then
-- Group filter: all groups of the item must match
local groups = lfilter:sub(7):split(",")
ffilter = function(name, def)
for _, group in ipairs(groups) do
@ -356,6 +362,7 @@ function ui.apply_filter(player, filter, search_dir)
return true
end
else
-- Name filter: fuzzy match item names and descriptions
local player_info = minetest.get_player_information(player_name)
local lang = player_info and player_info.lang_code or ""
@ -368,35 +375,41 @@ function ui.apply_filter(player, filter, search_dir)
or llocaldesc and string.find(llocaldesc, lfilter, 1, true)
end
end
ui.filtered_items_list[player_name]={}
local is_itemdef_listable = ui.is_itemdef_listable
local filtered_items = {}
local category = ui.current_category[player_name] or 'all'
if category == 'all' then
for name, def in pairs(minetest.registered_items) do
if valid_def(def)
if is_itemdef_listable(def)
and ffilter(name, def) then
table.insert(ui.filtered_items_list[player_name], name)
table.insert(filtered_items, name)
end
end
elseif category == 'uncategorized' then
for name, def in pairs(minetest.registered_items) do
if (not ui.find_category(name))
and valid_def(def)
if is_itemdef_listable(def)
and not ui.find_category(name)
and ffilter(name, def) then
table.insert(ui.filtered_items_list[player_name], name)
table.insert(filtered_items, name)
end
end
else
for name,exists in pairs(ui.registered_category_items[category]) do
-- Any other category is selected
for name, exists in pairs(ui.registered_category_items[category]) do
local def = minetest.registered_items[name]
if exists and def
and valid_def(def)
and is_itemdef_listable(def)
and ffilter(name, def) then
table.insert(ui.filtered_items_list[player_name], name)
table.insert(filtered_items, name)
end
end
end
table.sort(ui.filtered_items_list[player_name])
ui.filtered_items_list_size[player_name] = #ui.filtered_items_list[player_name]
table.sort(filtered_items)
ui.filtered_items_list_size[player_name] = #filtered_items
ui.filtered_items_list[player_name] = filtered_items
ui.current_index[player_name] = 1
ui.activefilter[player_name] = filter
ui.active_search_direction[player_name] = search_dir

View File

@ -7,17 +7,17 @@ Bag @1=Tasche @1
Small Bag=Kleine Tasche
Medium Bag=Mittelgroße Tasche
Large Bag=Große Tasche
All Items=
Misc. Items=
Plant Life=
Building Materials=
Tools=
Minerals and Metals=
Environment and Worldgen=
Lighting=
All Items=Alle Gegenstände
Misc. Items=Sonstige Gegenstände
Plant Life=Pfanzenwelt
Building Materials=Baumaterialien
Tools=Werkzeuge
Minerals and Metals=Minerale und Metalle
Environment and Worldgen=Umwelt und Welterstellung
Lighting=Beleuchtung
and = und
Scroll categories left=
Scroll categories right=
Scroll categories left=Kategorien nach links blättern
Scroll categories right=Kategorien nach rechts blättern
Search=Suchen
Reset search and display everything=Suche zurücksetzen und alles anzeigen
First page=Erste Seite
@ -76,10 +76,10 @@ Waypoints=Wegpunkte
Select Waypoint #@1=Wegpunkt Nr. @1 auswählen
Waypoint @1=Wegpunkt Nr. @1
Set waypoint to current location=Setze Wegpunkt zur derzeitigen Position
Hide waypoint=
Show waypoint=
Hide coordinates=
Show coordinates=
Hide waypoint=Wegpunkt verstecken
Show waypoint=Wegpunkt zeigen
Hide coordinates=Koordinaten verstecken
Show coordinates=Koordinaten zeigen
Change color of waypoint display=Farbe der Darstellung der Wegpunkte ändern
Edit waypoint name=Name des Wegpunkts ändern
Waypoint active=Wegpunkt aktiv

View File

@ -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

View File

@ -1,6 +1,6 @@
name = unified_inventory
optional_depends = default, creative, sfinv, datastorage, farming
optional_depends = default, creative, sfinv, datastorage
description = """
Unified Inventory replaces the default survival and creative inventory.
It adds a nicer interface and a number of features, such as a crafting guide.

View File

@ -207,11 +207,9 @@ ui.register_page("craft", {
local function stack_image_button(x, y, w, h, buttonname_prefix, item)
local name = item:get_name()
local count = item:get_count()
local wear = item:get_wear()
local description = item:get_meta():get_string("description")
local show_is_group = false
local displayitem = name.." "..count.." "..wear
local displayitem = item:to_string()
local selectitem = name
if name:sub(1, 6) == "group:" then
local group_name = name:sub(7)
@ -245,6 +243,9 @@ local function stack_image_button(x, y, w, h, buttonname_prefix, item)
return button
end
-- The recipe text contains parameters, hence they can yet not be translated.
-- Instead, use a dummy translation call so that it can be picked up by the
-- static parsing of the translation string update script
local recipe_text = {
recipe = NS("Recipe @1 of @2"),
usage = NS("Usage @1 of @2"),

View File

@ -10,5 +10,8 @@ unified_inventory_bags (Enable bags) bool true
#and the give privilege.
unified_inventory_trash (Enable trash) bool true
#If enabled, disabled buttons will be hidden instead of grayed out.
unified_inventory_hide_disabled_buttons (Hide disabled buttons) bool false
unified_inventory_automatic_categorization (Items automatically added to categories) bool true
unified_inventory_automatic_categorization (Items automatically added to categories) bool true