local revealed_cache = {} local function item_has_groups(item_groups, groups) for i = 1, #groups do local group = groups[i] if not item_groups[group] then return end end return true end local function revealed_show_recipe(recipe, playername) if not revealed_cache[playername] then revealed_cache[playername] = {} end if revealed_cache[playername][recipe] then return true end local reg_items = minetest.registered_items local revealed = doc.data.players[playername].stored_data.revealed for _, item in pairs(recipe.items) do local is_revealed_item = false if item:sub(1,6) == "group:" then local groups = item:sub(7):split(",") for cid, items in pairs(revealed) do for revealed_item in pairs(items) do if reg_items[revealed_item] and item_has_groups(reg_items[revealed_item].groups, groups) then is_revealed_item = true break end end if is_revealed_item then break end end else for cid, items in pairs(revealed) do if items[item] then is_revealed_item = true break end end end if not is_revealed_item then return false end end revealed_cache[playername][recipe] = true return true end local orig_get_usages = sfcg.get_usages function sfcg.get_usages(data, item) local recipes = orig_get_usages(data, item) if not recipes then return end local filtered = {} for _, recipe in ipairs(recipes) do if revealed_show_recipe(recipe, data.playername) then table.insert(filtered, recipe) end end if #filtered > 0 then return filtered end end local orig_get_recipes = sfcg.get_recipes function sfcg.get_recipes(data, item) local recipes = orig_get_recipes(data, item) if not recipes then return end local filtered = {} for _, recipe in ipairs(recipes) do if revealed_show_recipe(recipe, data.playername) then table.insert(filtered, recipe) end end if #filtered > 0 then return filtered end end local orig_execute_search = sfcg.execute_search function sfcg.execute_search(data) -- Only needed if doc is an optional dependency -- -- if not doc.data.players[data.playername] then -- -- Hack. craftguide is loaded before doc mod. Therefore doc is not initialized yet -- data.items = {} -- minetest.after(0, sfcg.execute_search, data) -- return -- end orig_execute_search(data) local filtered_items = {} for _, item in ipairs(data.items) do if sfcg.get_usages(data, item) or sfcg.get_recipes(data, item) then table.insert(filtered_items, item) end end data.items = filtered_items end -- Update sfinv inventory once in globalstep, if something revealed local async_update_users = {} local function async_update() for playername, _ in pairs(async_update_users) do sfcg.update_for_player(playername) async_update_users[playername] = nil end end local orig_mark_entry_as_revealed = doc.mark_entry_as_revealed function doc.mark_entry_as_revealed(playername, category_id, entry_id) -- Temp Fix: `doc.entry_revealed()` crashes on some items like farming:* because they're given the wrong category_id -- if not doc.entry_revealed(playername, category_id, entry_id) then orig_mark_entry_as_revealed(playername, category_id, entry_id) if not next(async_update_users) then minetest.after(0, async_update) async_update_users[playername] = true end -- end end minetest.register_on_leaveplayer(function(player) revealed_cache[player:get_player_name()] = nil end)