Make usages caching much faster and other fixes

This commit is contained in:
Paul Ouellette 2020-04-19 13:51:42 -04:00
parent 9e8c8d4436
commit 1339fefa4b

View file

@ -92,7 +92,10 @@ local function groups_to_item(groups)
end end
local function get_craftable_recipes(output) local function get_craftable_recipes(output)
local recipes = minetest.get_all_craft_recipes(output) or {} local recipes = minetest.get_all_craft_recipes(output)
if not recipes then
return
end
for i = #recipes, 1, -1 do for i = #recipes, 1, -1 do
for _, item in pairs(recipes[i].items) do for _, item in pairs(recipes[i].items) do
@ -110,72 +113,57 @@ local function get_craftable_recipes(output)
return recipes return recipes
end end
local function item_in_recipe(item, recipe) local function show_item(def)
for _, recipe_item in pairs(recipe.items) do return def.groups.not_in_craft_guide ~= 1 and def.description ~= ""
if recipe_item == item then
return true
end
end
return false
end end
-- If item can be used in recipe because recipe takes a `group:` item that item local function cache_usages(recipe)
-- matches, return a copy of recipe with the `group:` item replaced with item. local added = {}
local function groups_item_in_recipe(item, recipe) for _, item in pairs(recipe.items) do
local item_groups = minetest.registered_items[item].groups if not added[item] then
local groups = extract_groups(item)
for _, recipe_item in pairs(recipe.items) do if groups then
local groups = extract_groups(recipe_item) for name, def in pairs(minetest.registered_items) do
if groups and item_has_groups(item_groups, groups) then if not added[name] and show_item(def)
and item_has_groups(def.groups, groups) then
local usage = table.copy(recipe) local usage = table.copy(recipe)
table_replace(usage.items, recipe_item, item) table_replace(usage.items, item, name)
return usage usages_cache[name] = usages_cache[name] or {}
table.insert(usages_cache[name], usage)
added[name] = true
end end
end end
elseif show_item(minetest.registered_items[item]) then
usages_cache[item] = usages_cache[item] or {}
table.insert(usages_cache[item], recipe)
end end
added[item] = true
local function get_usages(item)
local usages = {}
for _, recipes in pairs(recipes_cache) do
for _, recipe in ipairs(recipes) do
if item_in_recipe(item, recipe) then
table.insert(usages, recipe)
else
recipe = groups_item_in_recipe(item, recipe)
if recipe then
table.insert(usages, recipe)
end end
end end
end end
end
return usages
end
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
for name, def in pairs(minetest.registered_items) do for name, def in pairs(minetest.registered_items) do
if def.groups.not_in_craft_guide ~= 1 and def.description ~= "" then if show_item(def) then
recipes_cache[name] = get_craftable_recipes(name) local recipes = get_craftable_recipes(name)
if recipes then
recipes_cache[name] = recipes
for _, recipe in ipairs(recipes) do
cache_usages(recipe)
end
end
end end
end end
for name, def in pairs(minetest.registered_items) do for name, def in pairs(minetest.registered_items) do
if def.groups.not_in_craft_guide ~= 1 and def.description ~= "" then if recipes_cache[name] or usages_cache[name] then
usages_cache[name] = get_usages(name)
if #recipes_cache[name] > 0 or #usages_cache[name] > 0 then
table.insert(init_items, name) table.insert(init_items, name)
end end
end end
end
table.sort(init_items) table.sort(init_items)
end) end)
local function is_fuel(item) local function is_fuel(item)
return minetest.get_craft_result({ return minetest.get_craft_result({method="fuel", items={item}}).time > 0
method = "fuel",
width = 1,
items = {item}
}).time > 0
end end
local function item_button_fs(fs, x, y, item, element_name, groups) local function item_button_fs(fs, x, y, item, element_name, groups)
@ -195,7 +183,7 @@ local function item_button_fs(fs, x, y, item, element_name, groups)
tooltip = S("Any item belonging to the group(s): @1", groupstr) tooltip = S("Any item belonging to the group(s): @1", groupstr)
end end
elseif is_fuel(item) then elseif is_fuel(item) then
local itemdef = minetest.registered_items[item] local itemdef = minetest.registered_items[item:match("%S*")]
local desc = itemdef and itemdef.description or S("Unknown Item") local desc = itemdef and itemdef.description or S("Unknown Item")
tooltip = desc.."\n"..minetest.colorize("orange", S("Fuel")) tooltip = desc.."\n"..minetest.colorize("orange", S("Fuel"))
end end
@ -264,10 +252,11 @@ local function get_formspec(player)
data.pagemax = math.max(1, math.ceil(#data.items / 32)) data.pagemax = math.max(1, math.ceil(#data.items / 32))
local fs = {} local fs = {}
table.insert(fs, "field[0.3,4.2;2.8,1.2;filter;;"..esc(data.filter).."]")
table.insert(fs, ("label[5.8,4.15;%s / %d]")
:format(minetest.colorize("yellow", data.pagenum), data.pagemax))
table.insert(fs, table.insert(fs,
"style_type[item_image_button;padding=2]"..
"field[0.3,4.2;2.8,1.2;filter;;"..esc(data.filter).."]"..
"label[5.8,4.15;"..minetest.colorize("yellow", data.pagenum).." / "..
data.pagemax.."]"..
"image_button[2.63,4.05;0.8,0.8;craftguide_search_icon.png;search;]".. "image_button[2.63,4.05;0.8,0.8;craftguide_search_icon.png;search;]"..
"image_button[3.25,4.05;0.8,0.8;craftguide_clear_icon.png;clear;]".. "image_button[3.25,4.05;0.8,0.8;craftguide_clear_icon.png;clear;]"..
"image_button[5,4.05;0.8,0.8;craftguide_prev_icon.png;prev;]".. "image_button[5,4.05;0.8,0.8;craftguide_prev_icon.png;prev;]"..
@ -293,7 +282,7 @@ local function get_formspec(player)
end end
end end
if #data.recipes > 0 then if data.recipes then
recipe_fs(fs, data) recipe_fs(fs, data)
elseif data.prev_item then elseif data.prev_item then
table.insert(fs, ("label[2,6.6;%s]"):format(esc(data.show_usages table.insert(fs, ("label[2,6.6;%s]"):format(esc(data.show_usages
@ -326,7 +315,7 @@ local function reset_data(data)
data.filter = "" data.filter = ""
data.pagenum = 1 data.pagenum = 1
data.prev_item = nil data.prev_item = nil
data.recipes = {} data.recipes = nil
data.items = init_items data.items = init_items
end end
@ -405,7 +394,6 @@ minetest.register_on_joinplayer(function(player)
player_data[name] = { player_data[name] = {
filter = "", filter = "",
pagenum = 1, pagenum = 1,
recipes = {},
items = init_items items = init_items
} }
end) end)