mirror of
https://github.com/minetest-mods/craftguide.git
synced 2024-11-23 03:13:44 +01:00
Separate recipe filters and progressive mode
This commit is contained in:
parent
5625a0cb1c
commit
4289dea108
30
README.md
30
README.md
@ -42,21 +42,22 @@ craftguide.register_craft({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
### Progressive mode
|
### Recipe filters
|
||||||
|
|
||||||
#### `craftguide.add_progressive_filter(name, function(recipes, player))`
|
Recipe filters can be used to filter the recipes shown to players. Progressive
|
||||||
|
mode is implemented as a recipe filter.
|
||||||
|
|
||||||
This function adds a recipe filter when progressive mode is enabled.
|
#### `craftguide.add_recipe_filter(name, function(recipes, player))`
|
||||||
The default `craftguide` filter will still be used.
|
|
||||||
|
|
||||||
The function should return the recipes to be displayed, given the available
|
Adds a recipe filter with the given name. The filter function should return the
|
||||||
recipes and an `ObjectRef` to the user. Each recipe is a table of the form
|
recipes to be displayed, given the available recipes and an `ObjectRef` to the
|
||||||
returned by `minetest.get_craft_recipe`.
|
user. Each recipe is a table of the form returned by
|
||||||
|
`minetest.get_craft_recipe`.
|
||||||
|
|
||||||
Example function to hide recipes for items from a mod called "secretstuff":
|
Example function to hide recipes for items from a mod called "secretstuff":
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
craftguide.add_progressive_filter("Hide secretstuff", function(recipes)
|
craftguide.add_recipe_filter("Hide secretstuff", function(recipes)
|
||||||
local filtered = {}
|
local filtered = {}
|
||||||
for _, recipe in ipairs(recipes) do
|
for _, recipe in ipairs(recipes) do
|
||||||
if recipe.output:sub(1,12) ~= "secretstuff:" then
|
if recipe.output:sub(1,12) ~= "secretstuff:" then
|
||||||
@ -68,11 +69,14 @@ craftguide.add_progressive_filter("Hide secretstuff", function(recipes)
|
|||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `craftguide.set_progressive_filter(name, function(recipes, player))`
|
#### `craftguide.remove_recipe_filter(name)`
|
||||||
|
|
||||||
This function sets an unique recipe filter when progressive mode is enabled.
|
Removes the recipe filter with the given name.
|
||||||
The default `craftguide` progressive filter will be overridden.
|
|
||||||
|
|
||||||
#### `craftguide.get_progressive_filters()`
|
#### `craftguide.set_recipe_filter(name, function(recipe, player))`
|
||||||
|
|
||||||
This function returns all progressive filters that are applied to recipes in progressive mode.
|
Removes all recipe filters and adds a new one.
|
||||||
|
|
||||||
|
#### `craftguide.get_recipe_filters()`
|
||||||
|
|
||||||
|
Returns a map of recipe filters, indexed by name.
|
||||||
|
251
init.lua
251
init.lua
@ -66,7 +66,6 @@ local function table_clean(t)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sort(ct)
|
|
||||||
return ct
|
return ct
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -107,6 +106,50 @@ craftguide.register_craft({
|
|||||||
items = {"default:stone"},
|
items = {"default:stone"},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local recipe_filters = {}
|
||||||
|
|
||||||
|
function craftguide.add_recipe_filter(name, func)
|
||||||
|
recipe_filters[name] = func
|
||||||
|
end
|
||||||
|
|
||||||
|
function craftguide.remove_recipe_filter(name)
|
||||||
|
recipe_filters[name] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function craftguide.set_recipe_filter(name, func)
|
||||||
|
recipe_filters = {[name] = func}
|
||||||
|
end
|
||||||
|
|
||||||
|
function craftguide.get_recipe_filters()
|
||||||
|
return recipe_filters
|
||||||
|
end
|
||||||
|
|
||||||
|
local function apply_recipe_filters(recipes, player)
|
||||||
|
for _, filter in pairs(recipe_filters) do
|
||||||
|
recipes = filter(recipes, player)
|
||||||
|
end
|
||||||
|
|
||||||
|
return recipes
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_filtered_items(player)
|
||||||
|
local items = {}
|
||||||
|
|
||||||
|
for i = 1, #init_items do
|
||||||
|
local item = init_items[i]
|
||||||
|
local recipes = recipes_cache[item]
|
||||||
|
|
||||||
|
if recipes then
|
||||||
|
recipes = apply_recipe_filters(recipes, player)
|
||||||
|
if #recipes > 0 then
|
||||||
|
items[#items + 1] = item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return items
|
||||||
|
end
|
||||||
|
|
||||||
local function cache_recipes(output)
|
local function cache_recipes(output)
|
||||||
local recipes = mt.get_all_craft_recipes(output) or {}
|
local recipes = mt.get_all_craft_recipes(output) or {}
|
||||||
for i = 1, #craftguide.custom_crafts do
|
for i = 1, #craftguide.custom_crafts do
|
||||||
@ -427,24 +470,21 @@ local show_fs = function(player, name)
|
|||||||
if sfinv_only then
|
if sfinv_only then
|
||||||
sfinv.set_player_inventory_formspec(player)
|
sfinv.set_player_inventory_formspec(player)
|
||||||
else
|
else
|
||||||
local data = player_data[name]
|
show_formspec(name, "craftguide", make_formspec(name))
|
||||||
data.formspec = make_formspec(name)
|
|
||||||
show_formspec(name, "craftguide", data.formspec)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function filter_items(data)
|
local function search(data)
|
||||||
local filter = data.filter
|
local filter = data.filter
|
||||||
if searches[filter] then
|
if searches[filter] then
|
||||||
data.items = searches[filter]
|
data.items = searches[filter]
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local items_list = progressive_mode and data.p_items or init_items
|
|
||||||
local filtered_list, c = {}, 0
|
local filtered_list, c = {}, 0
|
||||||
|
|
||||||
for i = 1, #items_list do
|
for i = 1, #data.items_raw do
|
||||||
local item = items_list[i]
|
local item = data.items_raw[i]
|
||||||
local item_desc = reg_items[item].description:lower()
|
local item_desc = reg_items[item].description:lower()
|
||||||
|
|
||||||
if item:find(filter, 1, true) or item_desc:find(filter, 1, true) then
|
if item:find(filter, 1, true) or item_desc:find(filter, 1, true) then
|
||||||
@ -453,7 +493,7 @@ local function filter_items(data)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if not progressive_mode then
|
if not next(recipe_filters) then
|
||||||
-- Cache the results only if searched 2 times
|
-- Cache the results only if searched 2 times
|
||||||
if searches[filter] == nil then
|
if searches[filter] == nil then
|
||||||
searches[filter] = false
|
searches[filter] = false
|
||||||
@ -499,9 +539,8 @@ end
|
|||||||
|
|
||||||
local function get_inv_items(player)
|
local function get_inv_items(player)
|
||||||
local inv = player:get_inventory()
|
local inv = player:get_inventory()
|
||||||
local stacks = inv:get_list("main")
|
local main, craft = inv:get_list("main"), inv:get_list("craft")
|
||||||
local craftlist = inv:get_list("craft")
|
local stacks = table_merge(main, craft)
|
||||||
stacks = table_merge(stacks, craftlist)
|
|
||||||
|
|
||||||
local inv_items = {}
|
local inv_items = {}
|
||||||
for i = 1, #stacks do
|
for i = 1, #stacks do
|
||||||
@ -536,104 +575,14 @@ local function item_in_inv(item, inv_items)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function progressive_default_filter(recipes, player)
|
|
||||||
local name = player:get_player_name()
|
|
||||||
local data = player_data[name]
|
|
||||||
local inv_items = get_inv_items(player)
|
|
||||||
|
|
||||||
if data.inv_items then
|
|
||||||
inv_items = table_merge(data.inv_items, inv_items)
|
|
||||||
end
|
|
||||||
|
|
||||||
if #inv_items == 0 then
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
|
|
||||||
data.inv_items = inv_items
|
|
||||||
|
|
||||||
local filtered = {}
|
|
||||||
for i = 1, #recipes do
|
|
||||||
local recipe = recipes[i]
|
|
||||||
local recipe_in_inv = true
|
|
||||||
|
|
||||||
for _, item in pairs(recipe.items) do
|
|
||||||
if not item_in_inv(item, inv_items) then
|
|
||||||
recipe_in_inv = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if recipe_in_inv then
|
|
||||||
filtered[#filtered + 1] = recipe
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return filtered
|
|
||||||
end
|
|
||||||
|
|
||||||
local progressive_filters = {{
|
|
||||||
name = "Default filter",
|
|
||||||
func = progressive_default_filter,
|
|
||||||
}}
|
|
||||||
|
|
||||||
function craftguide.add_progressive_filter(name, func)
|
|
||||||
progressive_filters[#progressive_filters + 1] = {
|
|
||||||
name = name,
|
|
||||||
func = func,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function craftguide.set_progressive_filter(name, func)
|
|
||||||
progressive_filters = {{
|
|
||||||
name = name,
|
|
||||||
func = func,
|
|
||||||
}}
|
|
||||||
end
|
|
||||||
|
|
||||||
function craftguide.get_progressive_filters()
|
|
||||||
return progressive_filters
|
|
||||||
end
|
|
||||||
|
|
||||||
local function apply_progressive_filters(recipes, player)
|
|
||||||
for i = 1, #progressive_filters do
|
|
||||||
local func = progressive_filters[i].func
|
|
||||||
recipes = func(recipes, player)
|
|
||||||
end
|
|
||||||
|
|
||||||
return recipes
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_progressive_items(player, name)
|
|
||||||
local data = player_data[name]
|
|
||||||
local items = data and data.p_items or {}
|
|
||||||
|
|
||||||
for i = 1, #init_items do
|
|
||||||
local item = init_items[i]
|
|
||||||
local recipes = recipes_cache[item]
|
|
||||||
|
|
||||||
if recipes then
|
|
||||||
recipes = apply_progressive_filters(recipes, player)
|
|
||||||
if #recipes > 0 then
|
|
||||||
items[#items + 1] = item
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
items = table_clean(items)
|
|
||||||
return items
|
|
||||||
end
|
|
||||||
|
|
||||||
local function init_data(player, name)
|
local function init_data(player, name)
|
||||||
player_data[name] = {
|
player_data[name] = {
|
||||||
filter = "",
|
filter = "",
|
||||||
pagenum = 1,
|
pagenum = 1,
|
||||||
iX = sfinv_only and 8 or DEFAULT_SIZE,
|
iX = sfinv_only and 8 or DEFAULT_SIZE,
|
||||||
items = init_items,
|
items = init_items,
|
||||||
|
items_raw = init_items,
|
||||||
}
|
}
|
||||||
|
|
||||||
if progressive_mode then
|
|
||||||
local meta = player:get_meta()
|
|
||||||
player_data[name].inv_items = deserialize(meta:get_string("inv_items"))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function reset_data(data)
|
local function reset_data(data)
|
||||||
@ -642,7 +591,7 @@ local function reset_data(data)
|
|||||||
data.query_item = nil
|
data.query_item = nil
|
||||||
data.show_usages = nil
|
data.show_usages = nil
|
||||||
data.recipes = nil
|
data.recipes = nil
|
||||||
data.items = progressive_mode and data.p_items or init_items
|
data.items = data.items_raw
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_init_items()
|
local function get_init_items()
|
||||||
@ -681,13 +630,13 @@ local function on_receive_fields(player, fields)
|
|||||||
elseif (fields.key_enter_field == "filter" or fields.search) and
|
elseif (fields.key_enter_field == "filter" or fields.search) and
|
||||||
fields.filter ~= "" then
|
fields.filter ~= "" then
|
||||||
local fltr = fields.filter:lower()
|
local fltr = fields.filter:lower()
|
||||||
if not progressive_mode and data.filter == fltr then
|
if data.filter == fltr then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
data.filter = fltr
|
data.filter = fltr
|
||||||
data.pagenum = 1
|
data.pagenum = 1
|
||||||
filter_items(data)
|
search(data)
|
||||||
show_fs(player, name)
|
show_fs(player, name)
|
||||||
|
|
||||||
elseif fields.prev or fields.next then
|
elseif fields.prev or fields.next then
|
||||||
@ -728,8 +677,8 @@ local function on_receive_fields(player, fields)
|
|||||||
local is_fuel = fuel_cache[item]
|
local is_fuel = fuel_cache[item]
|
||||||
local recipes = recipes_cache[item]
|
local recipes = recipes_cache[item]
|
||||||
|
|
||||||
if progressive_mode and recipes then
|
if recipes then
|
||||||
recipes = apply_progressive_filters(recipes, player)
|
recipes = apply_recipe_filters(recipes, player)
|
||||||
end
|
end
|
||||||
|
|
||||||
local no_recipes = not recipes or #recipes == 0
|
local no_recipes = not recipes or #recipes == 0
|
||||||
@ -748,11 +697,7 @@ local function on_receive_fields(player, fields)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if data.show_usages then
|
if data.show_usages then
|
||||||
recipes = get_item_usages(item)
|
recipes = apply_recipe_filters(get_item_usages(item), player)
|
||||||
|
|
||||||
if progressive_mode then
|
|
||||||
recipes = apply_progressive_filters(recipes, player)
|
|
||||||
end
|
|
||||||
|
|
||||||
if #recipes == 0 then
|
if #recipes == 0 then
|
||||||
return
|
return
|
||||||
@ -782,9 +727,9 @@ if sfinv_only then
|
|||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
local data = player_data[name]
|
local data = player_data[name]
|
||||||
|
|
||||||
if progressive_mode then
|
if next(recipe_filters) then
|
||||||
data.p_items = get_progressive_items(player, name)
|
data.items_raw = get_filtered_items(player)
|
||||||
filter_items(data)
|
search(data)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@ -803,13 +748,12 @@ else
|
|||||||
local name = user:get_player_name()
|
local name = user:get_player_name()
|
||||||
local data = player_data[name]
|
local data = player_data[name]
|
||||||
|
|
||||||
if progressive_mode then
|
if next(recipe_filters) then
|
||||||
data.p_items = get_progressive_items(user, name)
|
data.items_raw = get_filtered_items(user)
|
||||||
filter_items(data)
|
search(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
data.formspec = make_formspec(name)
|
show_formspec(name, "craftguide", make_formspec(name))
|
||||||
show_formspec(name, "craftguide", data.formspec)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
mt.register_craftitem("craftguide:book", {
|
mt.register_craftitem("craftguide:book", {
|
||||||
@ -886,7 +830,7 @@ else
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if not progressive_mode then
|
if not next(recipe_filters) then
|
||||||
mt.register_chatcommand("craft", {
|
mt.register_chatcommand("craft", {
|
||||||
description = S("Show recipe(s) of the pointed node"),
|
description = S("Show recipe(s) of the pointed node"),
|
||||||
func = function(name)
|
func = function(name)
|
||||||
@ -947,29 +891,64 @@ mt.register_on_joinplayer(function(player)
|
|||||||
init_data(player, name)
|
init_data(player, name)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local function save_meta(player, data)
|
|
||||||
local meta = player:get_meta()
|
|
||||||
meta:set_string("inv_items", serialize(data.inv_items))
|
|
||||||
end
|
|
||||||
|
|
||||||
mt.register_on_leaveplayer(function(player)
|
mt.register_on_leaveplayer(function(player)
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
if progressive_mode then
|
|
||||||
save_meta(player, player_data[name])
|
|
||||||
end
|
|
||||||
|
|
||||||
player_data[name] = nil
|
player_data[name] = nil
|
||||||
end)
|
end)
|
||||||
|
|
||||||
if progressive_mode then
|
if progressive_mode then
|
||||||
|
local function recipe_in_inv(recipe, inv_items)
|
||||||
|
for _, item in pairs(recipe.items) do
|
||||||
|
if not item_in_inv(item, inv_items) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function progressive_filter(recipes, player)
|
||||||
|
local name = player:get_player_name()
|
||||||
|
local discovered = player_data[name].inv_items
|
||||||
|
local inv_items = get_inv_items(player)
|
||||||
|
discovered = table_clean(table_merge(discovered, inv_items))
|
||||||
|
|
||||||
|
if #discovered == 0 then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local filtered = {}
|
||||||
|
for i = 1, #recipes do
|
||||||
|
local recipe = recipes[i]
|
||||||
|
if recipe_in_inv(recipe, discovered) then
|
||||||
|
filtered[#filtered + 1] = recipe
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return filtered
|
||||||
|
end
|
||||||
|
|
||||||
|
craftguide.add_recipe_filter("Default progressive filter", progressive_filter)
|
||||||
|
|
||||||
|
mt.register_on_joinplayer(function(player)
|
||||||
|
local meta = player:get_meta()
|
||||||
|
local inv_items = deserialize(meta:get_string("inv_items")) or {}
|
||||||
|
local name = player:get_player_name()
|
||||||
|
player_data[name].inv_items = inv_items
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function save_meta(player)
|
||||||
|
local meta = player:get_meta()
|
||||||
|
local name = player:get_player_name()
|
||||||
|
meta:set_string("inv_items", serialize(player_data[name].inv_items))
|
||||||
|
end
|
||||||
|
|
||||||
|
mt.register_on_leaveplayer(save_meta)
|
||||||
|
|
||||||
mt.register_on_shutdown(function()
|
mt.register_on_shutdown(function()
|
||||||
local players = mt.get_connected_players()
|
local players = mt.get_connected_players()
|
||||||
for i = 1, #players do
|
for i = 1, #players do
|
||||||
local player = players[i]
|
save_meta(players[i])
|
||||||
if player then
|
|
||||||
local name = player:get_player_name()
|
|
||||||
save_meta(player, player_data[name])
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user