Compare commits

...

11 Commits

Author SHA1 Message Date
Jean-Patrick Guerrero f379998943 Optimization 2021-02-08 21:19:36 +01:00
Jean-Patrick Guerrero bf9066a539 Use get_short_description 2021-02-08 01:26:07 +01:00
Jean-Patrick Guerrero a6a42b5970 Back to absolute font sizes 2021-01-25 19:36:10 +01:00
Jean-Patrick Guerrero 7613e7dacb Luacheck cleanup + API doc 2021-01-23 21:22:41 +01:00
Jean-Patrick Guerrero 03e9538886 Merge branch 'master' of https://github.com/minetest-mods/craftguide 2021-01-23 01:55:32 +01:00
Jean-Patrick Guerrero fcf30daca2 Better string formatting 2021-01-23 01:55:23 +01:00
SmallJoker eeca37be0f Fix error when closing a /craft formspec
Since 5.4.0-dev, hud_change() expects a valid HUD identifier. Nil results in an error.
Additionally data.hud_flags were 'nil' after closing the /craft-opened formspec
2021-01-22 16:40:30 +01:00
Jean-Patrick Guerrero 1cd2bd21d7 Fix mispelling 2021-01-16 22:01:55 +01:00
Jean-Patrick Guerrero d8039c04a8 Small tweak 2021-01-10 03:43:06 +01:00
Jean-Patrick Guerrero 8796170637 New slot texture 2021-01-07 20:42:26 +01:00
Jean-Patrick Guerrero 1e7e41c73e Fix bug 2021-01-02 12:22:00 +01:00
4 changed files with 88 additions and 70 deletions

View File

@ -1,4 +1,3 @@
unused_args = false
allow_defined_top = true allow_defined_top = true
read_globals = { read_globals = {

49
API.md
View File

@ -97,7 +97,7 @@ mode is implemented as a recipe filter.
#### `craftguide.add_recipe_filter(name, function(recipes, player))` #### `craftguide.add_recipe_filter(name, function(recipes, player))`
Adds a recipe filter with the given name. The filter function should return the Adds a recipe filter with the given `name`. The filter function returns the
recipes to be displayed, given the available recipes and an `ObjectRef` to the recipes to be displayed, given the available recipes and an `ObjectRef` to the
user. Each recipe is a table of the form returned by user. Each recipe is a table of the form returned by
`minetest.get_craft_recipe`. `minetest.get_craft_recipe`.
@ -123,7 +123,7 @@ Removes all recipe filters and adds a new one.
#### `craftguide.remove_recipe_filter(name)` #### `craftguide.remove_recipe_filter(name)`
Removes the recipe filter with the given name. Removes the recipe filter with the given `name`.
#### `craftguide.get_recipe_filters()` #### `craftguide.get_recipe_filters()`
@ -134,50 +134,41 @@ Returns a map of recipe filters, indexed by name.
### Search filters ### Search filters
Search filters are used to perform specific searches inside the search field. Search filters are used to perform specific searches inside the search field.
They can be used like so: `<optional name>+<filter name>=<value1>,<value2>,<...>` You can cumulate several filters to perform a specific search.
They can be used like so: `<optional_name> +<filter name>=<value1>,<value2>,<...>`
Examples: Example usages:
- `+groups=cracky,crumbly`: search for groups `cracky` and `crumbly` in all items. - `+groups=cracky,crumbly`: search for groups `cracky` and `crumbly` in all items.
- `sand+groups=falling_node`: search for group `falling_node` for items which contain `sand` in their names. - `wood +groups=flammable +type=node`: search for group `flammable` amongst items which contain
`wood` in their names AND have a `node` drawtype.
Notes: Notes:
- If `optional name` is omitted, the search filter will apply to all items, without pre-filtering. - If `optional_name` is omitted, the search filter will apply to all items, without pre-filtering.
- Filters can be combined. - The `groups` and `type` filters are currently implemented by default.
- The `groups` filter is currently implemented by default.
#### `craftguide.add_search_filter(name, function(item, values))` #### `craftguide.add_search_filter(name, function(item, values))`
Adds a search filter with the given name. Adds a search filter with the given `name`.
The search function should return a boolean value (whether the given item should be listed or not). The search function must return a boolean value (whether the given item should be listed or not).
Example function to show items which contain at least a recipe of given width(s): Example function sorting items by drawtype:
```lua ```lua
craftguide.add_search_filter("widths", function(item, widths) craftguide.add_search_filter("type", function(item, drawtype)
local has_width if drawtype == "node" then
local recipes = recipes_cache[item] return reg_nodes[item]
elseif drawtype == "item" then
if recipes then return reg_craftitems[item]
for i = 1, #recipes do elseif drawtype == "tool" then
local recipe_width = recipes[i].width return reg_tools[item]
for j = 1, #widths do
local width = tonumber(widths[j])
if width == recipe_width then
has_width = true
break
end
end
end
end end
return has_width
end) end)
``` ```
#### `craftguide.remove_search_filter(name)` #### `craftguide.remove_search_filter(name)`
Removes the search filter with the given name. Removes the search filter with the given `name`.
#### `craftguide.get_search_filters()` #### `craftguide.get_search_filters()`

108
init.lua
View File

@ -16,6 +16,8 @@ local http = core.request_http_api()
local singleplayer = core.is_singleplayer() local singleplayer = core.is_singleplayer()
local reg_items = core.registered_items local reg_items = core.registered_items
local reg_nodes = core.registered_nodes
local reg_craftitems = core.registered_craftitems
local reg_tools = core.registered_tools local reg_tools = core.registered_tools
local reg_entities = core.registered_entities local reg_entities = core.registered_entities
local reg_aliases = core.registered_aliases local reg_aliases = core.registered_aliases
@ -124,7 +126,7 @@ local fs_elements = {
} }
local styles = sprintf([[ local styles = sprintf([[
style_type[label,field;font_size=+0] style_type[label,field;font_size=16]
style_type[image_button;border=false;sound=craftguide_click] style_type[image_button;border=false;sound=craftguide_click]
style_type[item_image_button;border=false;bgimg_hovered=%s;sound=craftguide_click] style_type[item_image_button;border=false;bgimg_hovered=%s;sound=craftguide_click]
@ -142,8 +144,8 @@ local styles = sprintf([[
style[prev_usage;fgimg=%s;fgimg_hovered=%s] style[prev_usage;fgimg=%s;fgimg_hovered=%s]
style[next_usage;fgimg=%s;fgimg_hovered=%s] style[next_usage;fgimg=%s;fgimg_hovered=%s]
style[guide_mode,inv_mode;fgimg_hovered=%s;noclip=true;content_offset=0;sound=craftguide_tab] style[guide_mode,inv_mode;fgimg_hovered=%s;noclip=true;content_offset=0;sound=craftguide_tab]
style[pagenum,no_item,no_rcp;border=false;font=bold;font_size=+2;content_offset=0] style[pagenum,no_item,no_rcp;border=false;font=bold;font_size=18;content_offset=0]
style[craft_rcp,craft_usg;border=false;noclip=true;font_size=+0;sound=craftguide_craft; style[craft_rcp,craft_usg;border=false;noclip=true;font_size=16;sound=craftguide_craft;
bgimg=craftguide_btn9.png;bgimg_hovered=craftguide_btn9_hovered.png; bgimg=craftguide_btn9.png;bgimg_hovered=craftguide_btn9_hovered.png;
bgimg_pressed=craftguide_btn9_pressed.png;bgimg_middle=4,6] bgimg_pressed=craftguide_btn9_pressed.png;bgimg_middle=4,6]
]], ]],
@ -263,6 +265,10 @@ local function msg(name, str)
return chat_send(name, sprintf("[craftguide] %s", str)) return chat_send(name, sprintf("[craftguide] %s", str))
end end
local function is_num(x)
return type(x) == "number"
end
local function is_str(x) local function is_str(x)
return type(x) == "string" return type(x) == "string"
end end
@ -597,7 +603,7 @@ local function snip(str, limit)
return #str > limit and sprintf("%s...", sub(str, 1, limit - 3)) or str return #str > limit and sprintf("%s...", sub(str, 1, limit - 3)) or str
end end
local function get_desc(item, lang_code) local function get_desc(item)
if sub(item, 1, 1) == "_" then if sub(item, 1, 1) == "_" then
item = sub(item, 2) item = sub(item, 2)
end end
@ -605,11 +611,10 @@ local function get_desc(item, lang_code)
local def = reg_items[item] local def = reg_items[item]
if def then if def then
local desc = def.description local desc = ItemStack(item):get_short_description()
desc = lang_code and translate(lang_code, desc) or desc
if true_str(desc) then if true_str(desc) then
desc = desc:trim():match("[^\n]*") desc = desc:trim()
if not find(desc, "%u") then if not find(desc, "%u") then
desc = toupper(desc) desc = toupper(desc)
@ -820,7 +825,7 @@ local function cache_recipes(item)
end end
end end
local function get_recipes(item, data, player) local function get_recipes(player, item)
local clean_item = reg_aliases[item] or item local clean_item = reg_aliases[item] or item
local recipes = recipes_cache[clean_item] local recipes = recipes_cache[clean_item]
local usages = usages_cache[clean_item] local usages = usages_cache[clean_item]
@ -1069,7 +1074,7 @@ local function craft_stack(player, pname, data, craft_rcp)
end end
end end
local function select_item(player, name, data, _f) local function select_item(player, data, _f)
local item local item
for field in pairs(_f) do for field in pairs(_f) do
@ -1093,7 +1098,7 @@ local function select_item(player, name, data, _f)
if item == data.query_item then return end if item == data.query_item then return end
local recipes, usages = get_recipes(item, data, player) local recipes, usages = get_recipes(player, item)
if not recipes and not usages then return end if not recipes and not usages then return end
data.query_item = item data.query_item = item
@ -1249,7 +1254,7 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz
local _name = sprintf("_%s", name) local _name = sprintf("_%s", name)
fs(fmt("item_image_button", fs(fmt("item_image_button",
X + 0.1, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, X + 0.11, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE,
sprintf("%s %u", name, count * (is_recipe and data.scrbar_rcp or data.scrbar_usg or 1)), sprintf("%s %u", name, count * (is_recipe and data.scrbar_rcp or data.scrbar_usg or 1)),
_name, "")) _name, ""))
@ -1436,15 +1441,18 @@ local function get_model_fs(fs, data, def, model_alias)
local _name local _name
if v.color then if v.color then
local hex = sprintf("%02x", v.color) if is_num(v.color) then
local hex = sprintf("%02x", v.color)
while #hex < 8 do while #hex < 8 do
hex = "0" .. hex hex = "0" .. hex
end
_name = sprintf("%s^[multiply:%s", v.name,
sprintf("#%s%s", sub(hex, 3), sub(hex, 1, 2)))
else
_name = sprintf("%s^[multiply:%s", v.name, v.color)
end end
_name = sprintf("%s^[multiply:%s", v.name,
sprintf("#%s%s", sub(hex, 3), sub(hex, 1, 2)))
elseif v.animation then elseif v.animation then
_name = sprintf("%s^[verticalframe:%u:0", v.name, v.animation.aspect_h) _name = sprintf("%s^[verticalframe:%u:0", v.name, v.animation.aspect_h)
end end
@ -1481,7 +1489,7 @@ local function get_header(fs, data)
end end
local desc_lim, name_lim = 32, 34 local desc_lim, name_lim = 32, 34
local desc = ESC(get_desc(data.query_item, data.lang_code)) local desc = ESC(get_desc(data.query_item))
local tech_name = data.query_item local tech_name = data.query_item
local X = data.xoffset + 1.05 local X = data.xoffset + 1.05
local Y1 = data.yoffset + 0.47 local Y1 = data.yoffset + 0.47
@ -1497,9 +1505,9 @@ local function get_header(fs, data)
tech_name = snip(tech_name, name_lim) tech_name = snip(tech_name, name_lim)
end end
fs("style_type[label;font=bold;font_size=+6]", fs("style_type[label;font=bold;font_size=22]",
fmt("label", X, Y1, desc), "style_type[label;font=mono;font_size=+0]", fmt("label", X, Y1, desc), "style_type[label;font=mono;font_size=16]",
fmt("label", X, Y2, clr("#7bf", tech_name)), "style_type[label;font=normal;font_size=+0]") fmt("label", X, Y2, clr("#7bf", tech_name)), "style_type[label;font=normal;font_size=16]")
local def = reg_items[data.query_item] local def = reg_items[data.query_item]
local model_alias = craftguide.model_alias[data.query_item] local model_alias = craftguide.model_alias[data.query_item]
@ -1511,7 +1519,7 @@ local function get_header(fs, data)
end end
end end
local function get_export_fs(fs, data, panel, is_recipe, is_usage, max_stacks_rcp, max_stacks_usg) local function get_export_fs(fs, data, is_recipe, is_usage, max_stacks_rcp, max_stacks_usg)
local name = is_recipe and "rcp" or "usg" local name = is_recipe and "rcp" or "usg"
local show_export = (is_recipe and data.export_rcp) or (is_usage and data.export_usg) local show_export = (is_recipe and data.export_rcp) or (is_usage and data.export_usg)
@ -1541,8 +1549,7 @@ local function get_export_fs(fs, data, panel, is_recipe, is_usage, max_stacks_rc
fmt("scrollbar", fmt("scrollbar",
data.xoffset + 8.1, data.yoffset, 3, 0.35, sprintf("scrbar_%s", name), stack_fs), data.xoffset + 8.1, data.yoffset, 3, 0.35, sprintf("scrbar_%s", name), stack_fs),
fmt("button", data.xoffset + 8.1, data.yoffset + 0.4, 3, 0.7, sprintf("craft_%s", name), fmt("button", data.xoffset + 8.1, data.yoffset + 0.4, 3, 0.7, sprintf("craft_%s", name),
sprintf("%s", sprintf(stack_fs > 1 and ES"Craft %u items" or ES"Craft %u item", ES("Craft (x@1)", stack_fs)))
stack_fs))))
end end
local function get_rcp_extra(player, fs, data, panel, is_recipe, is_usage) local function get_rcp_extra(player, fs, data, panel, is_recipe, is_usage)
@ -1571,8 +1578,7 @@ local function get_rcp_extra(player, fs, data, panel, is_recipe, is_usage)
end end
if max_stacks_rcp > 0 or max_stacks_usg > 0 then if max_stacks_rcp > 0 or max_stacks_usg > 0 then
get_export_fs(fs, data, panel, is_recipe, is_usage, max_stacks_rcp, get_export_fs(fs, data, is_recipe, is_usage, max_stacks_rcp, max_stacks_usg)
max_stacks_usg)
end end
get_rcp_lbl(fs, data, panel, rn, is_recipe) get_rcp_lbl(fs, data, panel, rn, is_recipe)
@ -1681,7 +1687,7 @@ local function get_item_list(fs, data, full_height)
fs(fmt("image", X, Y, 1, 1, PNG.slot)) fs(fmt("image", X, Y, 1, 1, PNG.slot))
end end
fs(fmt("item_image_button", X, Y, 1, 1, item, sprintf("%s_inv", item), "")) fs[#fs + 1] = fmt("item_image_button", X, Y, 1, 1, item, sprintf("%s_inv", item), "")
end end
end end
@ -1752,14 +1758,21 @@ local function search(data)
local def = reg_items[item] local def = reg_items[item]
local desc = lower(translate(data.lang_code, def and def.description)) or "" local desc = lower(translate(data.lang_code, def and def.description)) or ""
local search_in = sprintf("%s %s", item, desc) local search_in = sprintf("%s %s", item, desc)
local to_add local temp, j, to_add = {}, 1
if search_filter then if search_filter then
for filter_name, values in pairs(filters) do for filter_name, values in pairs(filters) do
if values then if values then
local func = search_filters[filter_name] local func = search_filters[filter_name]
to_add = func(item, values) and (search_filter == "" or to_add = (j > 1 and temp[item] or j == 1) and
func(item, values) and (search_filter == "" or
find(search_in, search_filter, 1, true)) find(search_in, search_filter, 1, true))
if to_add then
temp[item] = true
end
j = j + 1
end end
end end
else else
@ -1799,6 +1812,16 @@ craftguide.add_search_filter("groups", function(item, groups)
return has_groups return has_groups
end) end)
craftguide.add_search_filter("type", function(item, drawtype)
if drawtype == "node" then
return reg_nodes[item]
elseif drawtype == "item" then
return reg_craftitems[item]
elseif drawtype == "tool" then
return reg_tools[item]
end
end)
--[[ As `core.get_craft_recipe` and `core.get_all_craft_recipes` do not --[[ As `core.get_craft_recipe` and `core.get_all_craft_recipes` do not
return the fuel, replacements and toolrepair recipes, we have to return the fuel, replacements and toolrepair recipes, we have to
override `core.register_craft` and do some reverse engineering. override `core.register_craft` and do some reverse engineering.
@ -1927,7 +1950,7 @@ local function get_init_items()
end end
end end
local function init_data(player, name) local function init_data(name)
local info = get_player_info(name) local info = get_player_info(name)
pdata[name] = { pdata[name] = {
@ -1961,7 +1984,7 @@ on_mods_loaded(get_init_items)
on_joinplayer(function(player) on_joinplayer(function(player)
local name = player:get_player_name() local name = player:get_player_name()
init_data(player, name) init_data(name)
local data = pdata[name] local data = pdata[name]
if data.fs_version < MIN_FORMSPEC_VERSION then if data.fs_version < MIN_FORMSPEC_VERSION then
@ -1979,12 +2002,17 @@ on_receive_fields(function(player, formname, _f)
local sb_rcp, sb_usg = _f.scrbar_rcp, _f.scrbar_usg local sb_rcp, sb_usg = _f.scrbar_rcp, _f.scrbar_usg
if _f.quit then if _f.quit then
player:hud_change(data.vignette, "text", "") -- Neither the vignette nor hud_flags are available when /craft is used
data.vignette = nil if data.vignette then
player:hud_change(data.vignette, "text", "")
data.vignette = nil
end
data.hud_flags.crosshair = true if data.hud_flags then
player:hud_set_flags(data.hud_flags) data.hud_flags.crosshair = true
data.hud_flags = nil player:hud_set_flags(data.hud_flags)
data.hud_flags = nil
end
return false return false
@ -2075,7 +2103,7 @@ on_receive_fields(function(player, formname, _f)
elseif _f.craft_rcp or _f.craft_usg then elseif _f.craft_rcp or _f.craft_usg then
craft_stack(player, name, data, _f.craft_rcp) craft_stack(player, name, data, _f.craft_rcp)
else else
select_item(player, name, data, _f) select_item(player, data, _f)
end end
return true, show_fs(player, name) return true, show_fs(player, name)
@ -2116,7 +2144,7 @@ core.register_craftitem("craftguide:book", {
wield_image = PNG.book, wield_image = PNG.book,
stack_max = 1, stack_max = 1,
groups = {book = 1}, groups = {book = 1},
on_use = function(itemstack, user) on_use = function(_, user)
on_use(user) on_use(user)
end end
}) })
@ -2148,7 +2176,7 @@ core.register_node("craftguide:sign", {
meta:set_string("infotext", "Crafting Guide Sign") meta:set_string("infotext", "Crafting Guide Sign")
end, end,
on_rightclick = function(pos, node, user, itemstack) on_rightclick = function(_, _, user)
on_use(user) on_use(user)
end end
}) })

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 B

After

Width:  |  Height:  |  Size: 4.1 KiB