From 4c1177ac26f901f50533b9e49255f7e058bba300 Mon Sep 17 00:00:00 2001 From: Paul Ouellette Date: Sun, 13 Jan 2019 15:51:32 -0500 Subject: [PATCH] Cache recipes and fuel definitions And refactor lots of related stuff --- init.lua | 311 ++++++++++++++++++++++++------------------------------- 1 file changed, 136 insertions(+), 175 deletions(-) diff --git a/init.lua b/init.lua index ff8b22e..c2077e0 100644 --- a/init.lua +++ b/init.lua @@ -6,6 +6,8 @@ craftguide = { local mt = minetest local player_data = {} local init_items = {} +local recipes_cache = {} +local fuel_cache = {} local searches = {} local progressive_mode = mt.settings:get_bool("craftguide_progressive_mode") @@ -78,24 +80,9 @@ craftguide.register_craft({ items = {"default:stone"}, }) -local function get_recipe(output) - local recipe = mt.get_craft_recipe(output) - if recipe.items then - return recipe - end - - for i = 1, #craftguide.custom_crafts do - local custom_craft = craftguide.custom_crafts[i] - if custom_craft.output:match("%S*") == output then - return custom_craft - end - end - - return {} -end - -local function get_recipes(output) +local function cache_recipes(output) local recipes = mt.get_all_craft_recipes(output) or {} + for i = 1, #craftguide.custom_crafts do local custom_craft = craftguide.custom_crafts[i] if custom_craft.output:match("%S*") == output then @@ -103,7 +90,22 @@ local function get_recipes(output) end end - return recipes + if #recipes > 0 then + recipes_cache[output] = recipes + return true + end +end + +local function get_burntime(item) + return get_result({method = "fuel", width = 1, items = {item}}).time +end + +local function cache_fuel(item) + local burntime = get_burntime(item) + if burntime > 0 then + fuel_cache[item] = burntime + return true + end end local color_codes = { @@ -116,10 +118,6 @@ local function colorize(str, color) return mt.colorize(color_codes[color], str) end -local function get_fueltime(item) - return get_result({method = "fuel", width = 1, items = {item}}).time -end - local function extract_groups(str) return str:sub(7):split(",") end @@ -154,85 +152,59 @@ local function groups_to_item(groups) return "" end -local function get_tooltip(item, recipe_type, cooktime, groups) - local tooltip, item_desc = "tooltip[" .. item .. ";", "" - local fueltime = get_fueltime(item) - local has_extras = groups or recipe_type == "cooking" or fueltime > 0 - - if reg_items[item] then - if not groups then - item_desc = reg_items[item].description - end - else - return tooltip .. S("Unknown Item (@1)", item) .. "]" - end +local function get_tooltip(item, groups, cooktime, burntime) + local tooltip if groups then - local groupstr = "" + local groupstr = {} for i = 1, #groups do - groupstr = groupstr .. - colorize(groups[i]) .. (groups[i + 1] and ", " or "") + groupstr[#groupstr + 1] = colorize(groups[i]) end - - tooltip = tooltip .. - S("Any item belonging to the group(s)") .. ": " .. groupstr + groupstr = concat(groupstr, ", ") + tooltip = S("Any item belonging to the group(s):") .. " " .. groupstr + else + tooltip = reg_items[item].description end - if recipe_type == "cooking" then - tooltip = tooltip .. item_desc .. "\n" .. - S("Cooking time") .. ": " .. colorize(cooktime) + if cooktime then + tooltip = tooltip .. "\n" .. S("Cooking time:") .. " " .. + colorize(cooktime) end - if fueltime > 0 then - tooltip = tooltip .. item_desc .. "\n" .. - S("Burning time") .. ": " .. colorize(fueltime) + if burntime then + tooltip = tooltip .. "\n" .. S("Burning time:") .. " " .. + colorize(burntime) end - return has_extras and tooltip .. "]" or "" + return "tooltip[" .. item .. ";" .. tooltip .. "]" end -local function get_recipe_fs(iX, iY, xoffset, recipe_num, recipes, show_usage) - if not recipes[1] then - return "" - end - +local function get_recipe_fs(data, iY) local fs = {} + local recipe = data.recipes[data.rnum] + local width = recipe.width + local xoffset = data.iX / 2.15 - fs[#fs + 1] = fmt("button[%f,%f;%f,%f;%s;%s %u %s %u]", - iX - (sfinv_only and 2.2 or 2.6), - iY + (sfinv_only and 3.9 or 3.3), - 2.2, - 1, - "alternate", - show_usage and S("Usage") or S("Recipe"), - recipe_num, - S("of"), - #recipes) - - local recipe_type = recipes[recipe_num].type - local items = recipes[recipe_num].items - local width = recipes[recipe_num].width - - local cooktime = width - if recipe_type == "cooking" then - width = 1 + local cooktime + if recipe.type == "cooking" then + cooktime, width = width, 1 elseif width == 0 then - width = min(3, #items) + width = min(3, #recipe.items) end - local rows = ceil(maxn(items) / width) + local rows = ceil(maxn(recipe.items) / width) local rightest, btn_size, s_btn_size = 0, 1.1 if width > GRID_LIMIT or rows > GRID_LIMIT then fs[#fs + 1] = fmt("label[%f,%f;%s]", - (iX / 2) - 2, + (data.iX / 2) - 2, iY + 2.2, S("Recipe is too big to be displayed (@1x@2)", width, rows)) return concat(fs) end - for i, item in pairs(items) do + for i, item in pairs(recipe.items) do local X = ceil((i - 1) % width + xoffset - width) - (sfinv_only and 0 or 0.2) local Y = ceil(i / width + (iY + 2) - min(2, rows)) @@ -255,7 +227,6 @@ local function get_recipe_fs(iX, iY, xoffset, recipe_num, recipes, show_usage) end local label = groups and "\nG" or "" - local tltp = get_tooltip(item, recipe_type, cooktime, groups) fs[#fs + 1] = fmt("item_image_button[%f,%f;%f,%f;%s;%s;%s]", X, @@ -266,7 +237,11 @@ local function get_recipe_fs(iX, iY, xoffset, recipe_num, recipes, show_usage) item:match("%S*"), label) - fs[#fs + 1] = tltp + local burntime = fuel_cache[item] + + if groups or cooktime or burntime then + fs[#fs + 1] = get_tooltip(item, groups, cooktime, burntime) + end end local custom_recipe = craftguide.craft_types[recipe_type] @@ -289,12 +264,9 @@ local function get_recipe_fs(iX, iY, xoffset, recipe_num, recipes, show_usage) 0.5, 0.5, custom_recipe and custom_recipe.description or - recipe_type:gsub("^%l", string.upper)) + recipe.type:gsub("^%l", string.upper)) end - local output = recipes[recipe_num].output - local output_s = output:match("%S+") - local arrow_X = rightest + (s_btn_size or 1.1) local output_X = arrow_X + 0.9 @@ -305,7 +277,7 @@ local function get_recipe_fs(iX, iY, xoffset, recipe_num, recipes, show_usage) 0.7, "craftguide_arrow.png") - if output == "BURN" then + if recipe.type == "fuel" then fs[#fs + 1] = fmt("image[%f,%f;%f,%f;%s]", output_X, iY + (sfinv_only and 2.68 or 2.18), @@ -313,33 +285,46 @@ local function get_recipe_fs(iX, iY, xoffset, recipe_num, recipes, show_usage) 1.1, "craftguide_fire.png") else + local output_name = recipe.output:match("%S+") + local burntime = fuel_cache[output_name] + fs[#fs + 1] = fmt("item_image_button[%f,%f;%f,%f;%s;%s;]", output_X, iY + (sfinv_only and 2.7 or 2.2), 1.1, 1.1, - output, - output_s) + recipe.output, + output_name) + + if burntime then + fs[#fs + 1] = get_tooltip(output_name, nil, nil, burntime) + + fs[#fs + 1] = fmt("image[%f,%f;%f,%f;%s]", + output_X + 1, + iY + (sfinv_only and 2.83 or 2.33), + 0.6, + 0.4, + "craftguide_arrow.png") + + fs[#fs + 1] = fmt("image[%f,%f;%f,%f;%s]", + output_X + 1.6, + iY + (sfinv_only and 2.68 or 2.18), + 0.6, + 0.6, + "craftguide_fire.png") + end end - fs[#fs + 1] = get_tooltip(output_s) - - local output_is_fuel = get_fueltime(output) > 0 - if output_is_fuel then - fs[#fs + 1] = fmt("image[%f,%f;%f,%f;%s]", - output_X + 1, - iY + (sfinv_only and 2.83 or 2.33), - 0.6, - 0.4, - "craftguide_arrow.png") - - fs[#fs + 1] = fmt("image[%f,%f;%f,%f;%s]", - output_X + 1.6, - iY + (sfinv_only and 2.68 or 2.18), - 0.6, - 0.6, - "craftguide_fire.png") - end + fs[#fs + 1] = fmt("button[%f,%f;%f,%f;%s;%s %u %s %u]", + data.iX - (sfinv_only and 2.2 or 2.6), + iY + (sfinv_only and 3.9 or 3.3), + 2.2, + 1, + "alternate", + data.show_usages and S("Usage") or S("Recipe"), + data.rnum, + S("of"), + #data.recipes) return concat(fs) end @@ -383,8 +368,6 @@ local function make_formspec(player_name) ",0.12;0.8,0.8;craftguide_next_icon.png;next;]" fs[#fs + 1] = "field[0.3,0.32;2.5,1;filter;;" .. mt.formspec_escape(data.filter) .. "]" - local xoffset = data.iX / 2.15 - if not next(data.items) then fs[#fs + 1] = fmt("label[%f,%f;%s]", (data.iX / 2) - 1, @@ -411,14 +394,8 @@ local function make_formspec(player_name) name) end - if data.input then - local usage = data.show_usage - fs[#fs + 1] = get_recipe_fs(data.iX, - iY, - xoffset, - data.rnum, - (usage and data.usages or data.recipes_item), - usage) + if data.recipes and #data.recipes > 0 then + fs[#fs + 1] = get_recipe_fs(data, iY) end fs = concat(fs) @@ -494,7 +471,7 @@ local function get_item_usages(item) get_recipe(name).items and def.description and def.description ~= "" then - local recipes = get_recipes(name) + local recipes = recipes_cache[name] for i = 1, #recipes do local recipe = recipes[i] if item_in_recipe(item, recipe) then @@ -504,6 +481,10 @@ local function get_item_usages(item) end end + if fuel_cache[item] then + usages[#usages + 1] = {type = "fuel", width = 1, items = {item}} + end + return usages end @@ -605,11 +586,13 @@ local function get_progressive_items(player) local items = {} for i = 1, #init_items do local item = init_items[i] - local recipes = get_recipes(item) - recipes = apply_progressive_filters(recipes, player) + local recipes = recipes_cache[item] - if #recipes > 0 then - items[#items + 1] = item + if recipes then + recipes = apply_progressive_filters(recipes, player) + if #recipes > 0 then + items[#items + 1] = item + end end end @@ -628,22 +611,22 @@ local function init_data(player, name) end local function reset_data(data) - data.show_usage = nil - data.filter = "" - data.input = nil - data.pagenum = 1 - data.rnum = 1 - data.items = progressive_mode and data.progressive_items or init_items + data.filter = "" + data.pagenum = 1 + data.query_item = nil + data.show_usages = nil + data.recipes = nil + data.items = progressive_mode and data.progressive_items or init_items end local function get_init_items() local c = 0 for name, def in pairs(reg_items) do - local is_fuel = get_fueltime(name) > 0 + local is_fuel = cache_fuel(name) if not (def.groups.not_in_craft_guide == 1 or def.groups.not_in_creative_inventory == 1) and - (get_recipe(name).items or is_fuel) and - def.description and def.description ~= "" then + def.description and def.description ~= "" and + (cache_recipes(name) or is_fuel) then c = c + 1 init_items[c] = name end @@ -663,18 +646,12 @@ local function on_receive_fields(player, fields) show_fs(player, player_name) elseif fields.alternate then - if #(data.show_usage and data.usages or data.recipes_item) == 1 then + if #data.recipes == 1 then return end - local next_i - if data.show_usage then - next_i = data.usages[data.rnum + 1] - else - next_i = data.recipes_item[data.rnum + 1] - end - - data.rnum = next_i and data.rnum + 1 or 1 + local num_next = data.rnum + 1 + data.rnum = data.recipes[num_next] and num_next or 1 show_fs(player, player_name) elseif (fields.key_enter_field == "filter" or fields.search) and @@ -702,7 +679,7 @@ local function on_receive_fields(player, fields) elseif (fields.size_inc and data.iX < MAX_LIMIT) or (fields.size_dec and data.iX > MIN_LIMIT) then data.pagenum = 1 - data.iX = data.iX - (fields.size_dec and 1 or -1) + data.iX = data.iX + (fields.size_inc and 1 or -1) show_fs(player, player_name) else @@ -720,51 +697,43 @@ local function on_receive_fields(player, fields) item = item:sub(1,-5) end - local is_fuel = get_fueltime(item) > 0 - local recipes = get_recipes(item) - if progressive_mode then + local is_fuel = fuel_cache[item] + local recipes = recipes_cache[item] + + if progressive_mode and recipes then recipes = apply_progressive_filters(recipes, player) end - local no_recipes = not next(recipes) + local no_recipes = not recipes or #recipes == 0 if no_recipes and not is_fuel then return end - if item ~= data.input then - data.show_usage = nil + if item ~= data.query_item then + data.show_usages = nil else - data.show_usage = not data.show_usage + data.show_usages = not data.show_usages end if is_fuel and no_recipes then - data.show_usage = true + data.show_usages = true end - if data.show_usage then - data.usages = get_item_usages(item) - - if is_fuel then - data.usages[#data.usages + 1] = { - width = 1, - type = "normal", - items = {item}, - output = "BURN", - } - end + if data.show_usages then + recipes = get_item_usages(item) if progressive_mode then - data.usages = apply_progressive_filters(data.usages, player) + recipes = apply_progressive_filters(recipes, player) end - if not next(data.usages) then - data.show_usage = nil + if not next(recipes) then + return end end - data.input = item - data.recipes_item = recipes - data.rnum = 1 + data.query_item = item + data.recipes = recipes + data.rnum = 1 show_fs(player, player_name) end @@ -923,9 +892,9 @@ if not progressive_mode then local data = player_data[name] reset_data(data) - local is_fuel = get_fueltime(node_name) > 0 - local recipes = get_recipes(node_name) + local recipes = recipes_cache[node_name] local no_recipes = not next(recipes) + local is_fuel = fuel_cache[node_name] if no_recipes and not is_fuel then return false, colorize("[craftguide] ", "red") .. @@ -934,23 +903,15 @@ if not progressive_mode then end if is_fuel and no_recipes then - data.usages = get_item_usages(node_name) - if is_fuel then - data.usages[#data.usages + 1] = { - width = 1, - type = "normal", - items = {node_name}, - output = "BURN", - } - end + recipes = get_item_usages(node_name) - if next(data.usages) then - data.show_usage = true + if next(recipes) then + data.show_usages = true end end - data.input = node_name - data.recipes_item = recipes + data.query_item = node_name + data.recipes = recipes return true, show_fs(player, name) end,