diff --git a/api.lua b/api.lua index 1609217..e4b67fa 100644 --- a/api.lua +++ b/api.lua @@ -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 @@ -201,8 +212,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 +230,7 @@ local function load_home() end io.close(input) end + load_home() function ui.set_home(player, pos) @@ -247,7 +259,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 +283,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 +299,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 +356,8 @@ ui.register_craft_type("digging_chance", { height = 1, }) +---------------- GUI registrations ---------------- + function ui.register_page(name, def) ui.pages[name] = def end @@ -361,6 +373,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 +389,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 +403,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 "") ) diff --git a/category.lua b/category.lua index d0fee5e..46b3e02 100644 --- a/category.lua +++ b/category.lua @@ -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 diff --git a/internal.lua b/internal.lua index 938ca19..3fbf5b7 100644 --- a/internal.lua +++ b/internal.lua @@ -329,7 +329,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 +342,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 +358,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 +371,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