Compare commits

...

35 Commits

Author SHA1 Message Date
f379998943 Optimization 2021-02-08 21:19:36 +01:00
bf9066a539 Use get_short_description 2021-02-08 01:26:07 +01:00
a6a42b5970 Back to absolute font sizes 2021-01-25 19:36:10 +01:00
7613e7dacb Luacheck cleanup + API doc 2021-01-23 21:22:41 +01:00
03e9538886 Merge branch 'master' of https://github.com/minetest-mods/craftguide 2021-01-23 01:55:32 +01:00
fcf30daca2 Better string formatting 2021-01-23 01:55:23 +01:00
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
1cd2bd21d7 Fix mispelling 2021-01-16 22:01:55 +01:00
d8039c04a8 Small tweak 2021-01-10 03:43:06 +01:00
8796170637 New slot texture 2021-01-07 20:42:26 +01:00
1e7e41c73e Fix bug 2021-01-02 12:22:00 +01:00
fcea88ac8c Remove useless stuff 2020-12-31 02:50:13 +01:00
8bde3fd86b Remove unused setting 2020-12-31 00:36:57 +01:00
fd764e2e36 Minor fix 2 2020-12-31 00:11:36 +01:00
d6083e2c03 Minor fix 2020-12-30 23:48:58 +01:00
42e255f07f Divorce inventory from craftguide (moved to my new repo "i3") 2020-12-30 23:41:21 +01:00
fab1c54234 WIP inventory mode 2020-12-30 23:13:09 +01:00
46c0d9e81b tweak icon 2020-12-28 21:15:11 +01:00
9e50192c54 New export icon 2020-12-28 20:50:02 +01:00
12aad9e55f Correct positioning 2020-12-28 03:30:15 +01:00
1fe30415f3 Update License 2020-12-26 20:49:09 +01:00
cce82cdbb4 Add vignette when opening the guide 2020-12-26 02:11:16 +01:00
63ae743a68 Small tweak 2020-12-26 01:18:49 +01:00
2e30413b52 Rename function 2020-12-25 23:12:25 +01:00
83832b4508 Add tooltips in header in case strings too long 2020-12-25 22:16:03 +01:00
e2864d9cd0 Minor teak 2020-12-25 21:22:10 +01:00
fa2910925e New screenshot 2020-12-25 20:59:47 +01:00
6cb4888722 New next/prev textures 2020-12-25 20:45:02 +01:00
7d9ddcb397 Tuning 2020-12-25 19:42:40 +01:00
75e1acad46 Rename file names 2020-12-25 19:25:48 +01:00
a5e913f3a4 New search icon 2020-12-25 19:21:19 +01:00
24fdd07f56 Minor fix 2020-12-24 23:12:38 +01:00
7e70ccab27 Minor tweaks 2020-12-22 22:14:57 +01:00
3bd2da9e32 Update Screenshot 2020-12-20 15:47:06 +01:00
b7bfa5a623 Little correction 2020-12-20 15:02:11 +01:00
20 changed files with 385 additions and 219 deletions

View File

@ -1,11 +1,8 @@
unused_args = false
allow_defined_top = true allow_defined_top = true
read_globals = { read_globals = {
"minetest", "minetest",
"default", "default",
"sfinv",
"sfinv_buttons",
"vector", "vector",
"string", "string",
"table", "table",

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()`

View File

@ -11,9 +11,6 @@ This crafting guide features a **progressive mode**.
This mode is a Terraria-like system that shows recipes you can craft This mode is a Terraria-like system that shows recipes you can craft
from items you ever had in your inventory. To enable it: `craftguide_progressive_mode = true` in `minetest.conf`. from items you ever had in your inventory. To enable it: `craftguide_progressive_mode = true` in `minetest.conf`.
`craftguide` is also integrated in `sfinv` (Minetest Game inventory). To enable it:
`craftguide_sfinv_only = true` in `minetest.conf`.
Use the command `/craft` to show the recipe(s) of the pointed node. Use the command `/craft` to show the recipe(s) of the pointed node.
For developers, `craftguide` also has a [modding API](https://github.com/minetest-mods/craftguide/blob/master/API.md). For developers, `craftguide` also has a [modding API](https://github.com/minetest-mods/craftguide/blob/master/API.md).
@ -21,4 +18,4 @@ For developers, `craftguide` also has a [modding API](https://github.com/minetes
Love this mod? Donations are appreciated: https://www.paypal.me/jpg84240 Love this mod? Donations are appreciated: https://www.paypal.me/jpg84240
![Preview2](https://i.imgur.com/JllwFGg.png) ![Preview2](https://user-images.githubusercontent.com/7883281/103141399-113b5e00-46f4-11eb-96cd-0167972ca1cf.png)

507
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
@ -78,22 +80,34 @@ local MIN_FORMSPEC_VERSION = 4
local PNG = { local PNG = {
bg = "craftguide_bg.png", bg = "craftguide_bg.png",
bg_full = "craftguide_bg_full.png", bg_full = "craftguide_bg_full.png",
search = "craftguide_search_icon.png", search = "craftguide_search.png",
prev = "craftguide_next_icon.png^\\[transformFX", prev = "craftguide_next.png^\\[transformFX",
next = "craftguide_next_icon.png", next = "craftguide_next.png",
arrow = "craftguide_arrow.png", arrow = "craftguide_arrow.png",
trash = "craftguide_trash.png",
sort_az = "craftguide_sort.png",
sort_za = "craftguide_sort2.png",
compress = "craftguide_compress.png",
fire = "craftguide_fire.png", fire = "craftguide_fire.png",
fire_anim = "craftguide_fire_anim.png", fire_anim = "craftguide_fire_anim.png",
book = "craftguide_book.png", book = "craftguide_book.png",
sign = "craftguide_sign.png", sign = "craftguide_sign.png",
cancel = "craftguide_cancel.png", cancel = "craftguide_cancel.png",
selected = "craftguide_selected.png", export = "craftguide_export.png",
slot = "craftguide_slot.png",
tab = "craftguide_tab.png",
furnace_anim = "craftguide_furnace_anim.png", furnace_anim = "craftguide_furnace_anim.png",
cancel_hover = "craftguide_cancel.png^\\[brighten", cancel_hover = "craftguide_cancel.png^\\[brighten",
search_hover = "craftguide_search_icon_hover.png", search_hover = "craftguide_search.png^\\[brighten",
prev_hover = "craftguide_next_icon_hover.png^\\[transformFX", export_hover = "craftguide_export.png^\\[brighten",
next_hover = "craftguide_next_icon_hover.png", trash_hover = "craftguide_trash.png^\\[brighten",
compress_hover = "craftguide_compress.png^\\[brighten",
sort_az_hover = "craftguide_sort.png^\\[brighten",
sort_za_hover = "craftguide_sort2.png^\\[brighten",
prev_hover = "craftguide_next_hover.png^\\[transformFX",
next_hover = "craftguide_next_hover.png",
tab_hover = "craftguide_tab_hover.png",
} }
local fs_elements = { local fs_elements = {
@ -104,43 +118,51 @@ local fs_elements = {
tooltip = "tooltip[%f,%f;%f,%f;%s]", tooltip = "tooltip[%f,%f;%f,%f;%s]",
item_image = "item_image[%f,%f;%f,%f;%s]", item_image = "item_image[%f,%f;%f,%f;%s]",
bg9 = "background9[%f,%f;%f,%f;%s;false;%u]", bg9 = "background9[%f,%f;%f,%f;%s;false;%u]",
model = "model[%f,%f;%f,%f;%s;%s;%s;0,0;true;true;%s]", model = "model[%f,%f;%f,%f;%s;%s;%s;%s;%s;true;%s]",
image_button = "image_button[%f,%f;%f,%f;%s;%s;%s]", image_button = "image_button[%f,%f;%f,%f;%s;%s;%s]",
animated_image = "animated_image[%f,%f;%f,%f;;%s;%u;%u]", animated_image = "animated_image[%f,%f;%f,%f;;%s;%u;%u]",
scrollbar = "scrollbar[%f,%f;%f,%f;horizontal;%s;%u]", scrollbar = "scrollbar[%f,%f;%f,%f;horizontal;%s;%u]",
item_image_button = "item_image_button[%f,%f;%f,%f;%s;%s;%s]", item_image_button = "item_image_button[%f,%f;%f,%f;%s;%s;%s]",
arrow = "image_button[%f,%f;0.7,0.7;%s;%s;;;false;%s]",
} }
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;bgimg_pressed=%s; style_type[item_image_button;border=false;bgimg_hovered=%s;sound=craftguide_click]
sound=craftguide_click]
style[filter;border=false] style[filter;border=false]
style[cancel;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s] style[cancel;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[search;fgimg=%s;fgimg_hovered=%s] style[search;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[prev_page;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s] style[trash;fgimg=%s;fgimg_hovered=%s;content_offset=0;sound=craftguide_delete]
style[next_page;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s] style[sort_az;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[prev_recipe;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s] style[sort_za;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[next_recipe;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s] style[compress;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[prev_usage;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s] style[prev_page;fgimg=%s;fgimg_hovered=%s]
style[next_usage;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s] style[next_page;fgimg=%s;fgimg_hovered=%s]
style[pagenum,no_item,no_rcp;border=false;font=bold;font_size=+2;content_offset=0] style[prev_recipe;fgimg=%s;fgimg_hovered=%s]
style[craft_rcp,craft_usg;border=false;noclip=true;font_size=+0;sound=craftguide_craft; style[next_recipe;fgimg=%s;fgimg_hovered=%s]
style[prev_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[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=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]
]], ]],
PNG.selected, PNG.selected, PNG.slot,
PNG.cancel, PNG.cancel_hover, PNG.cancel_hover, PNG.cancel, PNG.cancel_hover,
PNG.search, PNG.search_hover, PNG.search, PNG.search_hover,
PNG.prev, PNG.prev_hover, PNG.prev_hover, PNG.trash, PNG.trash_hover,
PNG.next, PNG.next_hover, PNG.next_hover, PNG.sort_az, PNG.sort_az_hover,
PNG.prev, PNG.prev_hover, PNG.prev_hover, PNG.sort_za, PNG.sort_za_hover,
PNG.next, PNG.next_hover, PNG.next_hover, PNG.compress, PNG.compress_hover,
PNG.prev, PNG.prev_hover, PNG.prev_hover, PNG.prev, PNG.prev_hover,
PNG.next, PNG.next_hover, PNG.next_hover) PNG.next, PNG.next_hover,
PNG.prev, PNG.prev_hover,
PNG.next, PNG.next_hover,
PNG.prev, PNG.prev_hover,
PNG.next, PNG.next_hover,
PNG.tab_hover)
local function get_lang_code(info) local function get_lang_code(info)
return info and info.lang_code return info and info.lang_code
@ -243,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
@ -577,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
@ -585,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)
@ -800,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]
@ -844,10 +869,86 @@ local function groups_to_items(groups, get_all)
return get_all and names or "" return get_all and names or ""
end end
local function get_stack_max(data, is_recipe, rcp) local function sort_itemlist(player, az)
data.inv = data.player:get_inventory() local inv = player:get_inventory()
local list = data.inv:get_list("main") local list = inv:get_list("main")
local size = data.inv:get_size("main") local size = inv:get_size("main")
local new_inv, stack_meta = {}, {}
for i = 1, size do
local stack = list[i]
local name = stack:get_name()
local count = stack:get_count()
local empty = stack:is_empty()
local meta = stack:get_meta():to_table()
if not empty then
if next(meta.fields) then
stack_meta[#stack_meta + 1] = stack
else
new_inv[#new_inv + 1] = sprintf("%s %u", name, count)
end
end
end
if az then
sort(new_inv)
else
sort(new_inv, function(a, b) return a > b end)
end
inv:set_list("main", new_inv)
for i = 1, #stack_meta do
inv:set_stack("main", #new_inv + i, stack_meta[i])
end
end
local function compress_items(player)
local inv = player:get_inventory()
local list = inv:get_list("main")
local size = inv:get_size("main")
local new_inv, _new_inv, stack_meta = {}, {}, {}
for i = 1, size do
local stack = list[i]
local name = stack:get_name()
local count = stack:get_count()
local empty = stack:is_empty()
local meta = stack:get_meta():to_table()
if not empty then
if next(meta.fields) then
stack_meta[#stack_meta + 1] = stack
else
new_inv[name] = new_inv[name] or 0
new_inv[name] = new_inv[name] + count
end
end
end
for name, count in pairs(new_inv) do
local stackmax = ItemStack(name):get_stack_max()
local iter = ceil(count / stackmax)
local leftover = count
for _ = 1, iter do
_new_inv[#_new_inv + 1] = sprintf("%s %u", name, min(stackmax, leftover))
leftover = leftover - stackmax
end
end
sort(_new_inv)
inv:set_list("main", _new_inv)
for i = 1, #stack_meta do
inv:set_stack("main", #_new_inv + i, stack_meta[i])
end
end
local function get_stack_max(inv, data, is_recipe, rcp)
local list = inv:get_list("main")
local size = inv:get_size("main")
local counts_inv, counts_rcp, counts = {}, {}, {} local counts_inv, counts_rcp, counts = {}, {}, {}
local rcp_usg = is_recipe and "recipe" or "usage" local rcp_usg = is_recipe and "recipe" or "usage"
@ -868,6 +969,8 @@ local function get_stack_max(data, is_recipe, rcp)
for name in pairs(counts_rcp) do for name in pairs(counts_rcp) do
if is_group(name) then if is_group(name) then
local def = reg_items[item] local def = reg_items[item]
if def then
local groups = extract_groups(name) local groups = extract_groups(name)
if item_has_groups(def.groups, groups) then if item_has_groups(def.groups, groups) then
@ -875,6 +978,7 @@ local function get_stack_max(data, is_recipe, rcp)
end end
end end
end end
end
counts_inv[item] = (counts_inv[item] or 0) + count counts_inv[item] = (counts_inv[item] or 0) + count
end end
@ -897,11 +1001,29 @@ local function get_stack_max(data, is_recipe, rcp)
return max_stacks return max_stacks
end end
local function get_stack(player, pname, stack, message)
local inv = player:get_inventory()
if inv:room_for_item("main", stack) then
inv:add_item("main", stack)
msg(pname, sprintf("%s added in your inventory", message))
else
local dir = player:get_look_dir()
local ppos = player:get_pos()
ppos.y = ppos.y + 1.625
local look_at = vec_add(ppos, vec_mul(dir, 1))
core.add_item(look_at, stack)
msg(pname, sprintf("%s spawned", message))
end
end
local function craft_stack(player, pname, data, craft_rcp) local function craft_stack(player, pname, data, craft_rcp)
local inv = player:get_inventory()
local rcp_usg = craft_rcp and "recipe" or "usage" local rcp_usg = craft_rcp and "recipe" or "usage"
local output = craft_rcp and data.recipes[data.rnum].output or data.usages[data.unum].output local output = craft_rcp and data.recipes[data.rnum].output or data.usages[data.unum].output
output = ItemStack(output) output = ItemStack(output)
local stackname, stackcount = output:get_name(), output:get_count() local stackname, stackcount, stackmax = output:get_name(), output:get_count(), output:get_stack_max()
local scrbar_val = data[sprintf("scrbar_%s", craft_rcp and "rcp" or "usg")] or 1 local scrbar_val = data[sprintf("scrbar_%s", craft_rcp and "rcp" or "usg")] or 1
for name, count in pairs(data.export_counts[rcp_usg].rcp) do for name, count in pairs(data.export_counts[rcp_usg].rcp) do
@ -927,32 +1049,28 @@ local function craft_stack(player, pname, data, craft_rcp)
end end
for k, v in pairs(items) do for k, v in pairs(items) do
data.inv:remove_item("main", sprintf("%s %s", k, v * scrbar_val)) inv:remove_item("main", sprintf("%s %s", k, v * scrbar_val))
end end
end end
local count = stackcount * scrbar_val local count = stackcount * scrbar_val
local stack = ItemStack(sprintf("%s %s", stackname, count))
local desc = get_desc(stackname) local desc = get_desc(stackname)
local iter = ceil(count / stackmax)
local leftover = count
for _ = 1, iter do
local c = min(stackmax, leftover)
local message local message
if count > 1 then if c > 1 then
message = clr("#ff0", sprintf("%s x %s", count, desc)) message = clr("#ff0", sprintf("%s x %s", c, desc))
else else
message = clr("#ff0", sprintf("%s", desc)) message = clr("#ff0", sprintf("%s", desc))
end end
if data.inv:room_for_item("main", stack) then local stack = ItemStack(sprintf("%s %s", stackname, c))
data.inv:add_item("main", stack) get_stack(player, pname, stack, message)
msg(pname, sprintf("%s added in your inventory", message)) leftover = leftover - stackmax
else
local dir = player:get_look_dir()
local ppos = player:get_pos()
ppos.y = ppos.y + 1.625
local look_at = vec_add(ppos, vec_mul(dir, 1))
core.add_item(look_at, stack)
msg(pname, sprintf("%s crafted", message))
end end
end end
@ -980,9 +1098,8 @@ local function select_item(player, 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
if data.show_usages and not usages then return end
data.query_item = item data.query_item = item
data.recipes = recipes data.recipes = recipes
@ -1124,7 +1241,7 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz
fs(fmt("image", arrow_X, Y + 0.06, 1, 1, PNG.arrow)) fs(fmt("image", arrow_X, Y + 0.06, 1, 1, PNG.arrow))
if rcp.type == "fuel" then if rcp.type == "fuel" then
fs(fmt("animated_image", X, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, PNG.fire_anim, 8, 180)) fs(fmt("animated_image", X + 0.05, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, PNG.fire_anim, 8, 180))
else else
local item = rcp.output local item = rcp.output
item = ItemStack(clean_name(item)) item = ItemStack(clean_name(item))
@ -1132,13 +1249,13 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz
local count = item:get_count() local count = item:get_count()
local bt_s = ITEM_BTN_SIZE * 1.2 local bt_s = ITEM_BTN_SIZE * 1.2
fs(fmt("image", X, Y - 0.11, bt_s, bt_s, PNG.selected)) fs(fmt("image", X, Y - 0.11, bt_s, bt_s, PNG.slot))
local _name = sprintf("_%s", name) local _name = sprintf("_%s", name)
fs(fmt("item_image_button", X + 0.1, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, fs(fmt("item_image_button",
sprintf("%s %u", name, X + 0.11, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE,
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, ""))
local def = reg_items[name] local def = reg_items[name]
@ -1240,7 +1357,7 @@ local function get_grid_fs(fs, data, rcp, is_recipe)
end end
if not large_recipe then if not large_recipe then
fs(fmt("image", X, Y, btn_size, btn_size, PNG.selected)) fs(fmt("image", X, Y, btn_size, btn_size, PNG.slot))
end end
local btn_name = groups and sprintf("group|%s|%s", groups[1], item) or item local btn_name = groups and sprintf("group|%s|%s", groups[1], item) or item
@ -1294,11 +1411,11 @@ local function get_rcp_lbl(fs, data, panel, rn, is_recipe)
local btn_suffix = is_recipe and "recipe" or "usage" local btn_suffix = is_recipe and "recipe" or "usage"
local prev_name = sprintf("prev_%s", btn_suffix) local prev_name = sprintf("prev_%s", btn_suffix)
local next_name = sprintf("next_%s", btn_suffix) local next_name = sprintf("next_%s", btn_suffix)
local x_arrow = data.xoffset + 4.9 local x_arrow = data.xoffset + 5.09
local y_arrow = data.yoffset + 3 local y_arrow = data.yoffset + 3.2
fs(fmt("arrow", x_arrow - shift, y_arrow, PNG.prev, prev_name, ""), fs(fmt("image_button", x_arrow - shift, y_arrow, 0.3, 0.3, "", prev_name, ""),
fmt("arrow", x_arrow + 2.3, y_arrow, PNG.next, next_name, "")) fmt("image_button", x_arrow + 2.3, y_arrow, 0.3, 0.3, "", next_name, ""))
end end
local rcp = is_recipe and panel.rcp[data.rnum] or panel.rcp[data.unum] local rcp = is_recipe and panel.rcp[data.rnum] or panel.rcp[data.unum]
@ -1324,6 +1441,7 @@ local function get_model_fs(fs, data, def, model_alias)
local _name local _name
if v.color then if v.color then
if is_num(v.color) then
local hex = sprintf("%02x", v.color) local hex = sprintf("%02x", v.color)
while #hex < 8 do while #hex < 8 do
@ -1332,7 +1450,9 @@ local function get_model_fs(fs, data, def, model_alias)
_name = sprintf("%s^[multiply:%s", v.name, _name = sprintf("%s^[multiply:%s", v.name,
sprintf("#%s%s", sub(hex, 3), sub(hex, 1, 2))) sprintf("#%s%s", sub(hex, 3), sub(hex, 1, 2)))
else
_name = sprintf("%s^[multiply:%s", v.name, v.color)
end
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
@ -1346,10 +1466,10 @@ local function get_model_fs(fs, data, def, model_alias)
fs(fmt("model", fs(fmt("model",
data.xoffset + 6.6, data.yoffset + 0.05, 1.3, 1.3, "", data.xoffset + 6.6, data.yoffset + 0.05, 1.3, 1.3, "",
def.mesh, concat(t, ","), model_alias and model_alias.frames or "")) def.mesh, concat(t, ","), "0,0", "true", model_alias and model_alias.frames or ""))
end end
local function get_title_fs(fs, data) local function get_header(fs, data)
local fav = is_fav(data.favs, data.query_item) local fav = is_fav(data.favs, data.query_item)
local nfavs = #data.favs local nfavs = #data.favs
local star_x, star_y, star_size = data.xoffset + 0.4, data.yoffset + 0.5, 0.4 local star_x, star_y, star_size = data.xoffset + 0.4, data.yoffset + 0.5, 0.4
@ -1368,13 +1488,26 @@ local function get_title_fs(fs, data)
sprintf("tooltip[nofav;%s]", ES"Cannot mark this item. Bookmark limit reached.")) sprintf("tooltip[nofav;%s]", ES"Cannot mark this item. Bookmark limit reached."))
end end
fs("style_type[label;font=bold;font_size=+6]", local desc_lim, name_lim = 32, 34
fmt("label", data.xoffset + 1.05, data.yoffset + 0.47, local desc = ESC(get_desc(data.query_item))
snip(ESC(get_desc(data.query_item, data.lang_code)), 32)), local tech_name = data.query_item
"style_type[label;font=mono;font_size=+0]", local X = data.xoffset + 1.05
fmt("label", data.xoffset + 1.05, data.yoffset + 0.97, local Y1 = data.yoffset + 0.47
clr("#7bf", snip(data.query_item, 34))), local Y2 = Y1 + 0.5
"style_type[label;font=normal]")
if #desc > desc_lim then
fs(fmt("tooltip", X, Y1 - 0.1, 5.7, 0.24, desc))
desc = snip(desc, desc_lim)
end
if #tech_name > name_lim then
fs(fmt("tooltip", X, Y2 - 0.1, 5.7, 0.24, tech_name))
tech_name = snip(tech_name, name_lim)
end
fs("style_type[label;font=bold;font_size=22]",
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=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]
@ -1382,31 +1515,22 @@ local function get_title_fs(fs, data)
if def.drawtype == "mesh" or model_alias then if def.drawtype == "mesh" or model_alias then
get_model_fs(fs, data, def, model_alias) get_model_fs(fs, data, def, model_alias)
else else
fs(fmt("item_image", fs(fmt("item_image", data.xoffset + 6.8, data.yoffset + 0.17, 1.1, 1.1, data.query_item))
data.xoffset + 6.8, data.yoffset + 0.17, 1.1, 1.1, data.query_item))
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)
fs(sprintf("style[export_%s;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s]", fs(sprintf("style[export_%s;fgimg=%s;fgimg_hovered=%s]",
name, sprintf("craftguide_export%s.png", show_export and "" or "_off"), name, sprintf("%s", show_export and PNG.export_hover or PNG.export), PNG.export_hover),
"craftguide_export.png", "craftguide_export.png"),
fmt("image_button", fmt("image_button",
data.xoffset + 7.35, data.yoffset + 0.2, 0.45, 0.45, "", data.xoffset + 7.35, data.yoffset + 0.2, 0.45, 0.45, "", sprintf("export_%s", name), ""),
sprintf("export_%s", name), ""),
sprintf("tooltip[export_%s;%s]", name, ES"Quick crafting")) sprintf("tooltip[export_%s;%s]", name, ES"Quick crafting"))
if not show_export then return end if not show_export then return end
local item = (is_recipe and panel.rcp[data.rnum].output) or
(is_usage and panel.rcp[data.unum].output)
item = clean_name(item)
local _name = match(item, "%S*")
local stack = ItemStack(_name)
local stack_max = stack:get_stack_max()
local craft_max = is_recipe and max_stacks_rcp or max_stacks_usg local craft_max = is_recipe and max_stacks_rcp or max_stacks_usg
local stack_fs = (is_recipe and data.scrbar_rcp) or (is_usage and data.scrbar_usg) or 1 local stack_fs = (is_recipe and data.scrbar_rcp) or (is_usage and data.scrbar_usg) or 1
@ -1421,28 +1545,28 @@ local function get_export_fs(fs, data, panel, is_recipe, is_usage, max_stacks_rc
end end
fs(sprintf("style[scrbar_%s;noclip=true]", name), fs(sprintf("style[scrbar_%s;noclip=true]", name),
sprintf("scrollbaroptions[min=1;max=%u;smallstep=1]", min(craft_max, stack_max)), sprintf("scrollbaroptions[min=1;max=%u;smallstep=1]", craft_max),
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 stacks" or ES"Craft %u stack", ES("Craft (x@1)", stack_fs)))
stack_fs))))
end end
local function get_rcp_extra(fs, data, panel, is_recipe, is_usage) local function get_rcp_extra(player, fs, data, panel, is_recipe, is_usage)
local rn = panel.rcp and #panel.rcp local rn = panel.rcp and #panel.rcp
if rn then if rn then
local rcp_normal = is_recipe and panel.rcp[data.rnum].type == "normal" local rcp_normal = is_recipe and panel.rcp[data.rnum].type == "normal"
local usg_normal = is_usage and panel.rcp[data.unum].type == "normal" local usg_normal = is_usage and panel.rcp[data.unum].type == "normal"
local max_stacks_rcp, max_stacks_usg = 0, 0 local max_stacks_rcp, max_stacks_usg = 0, 0
local inv = player:get_inventory()
if rcp_normal then if rcp_normal then
max_stacks_rcp = get_stack_max(data, is_recipe, panel.rcp[data.rnum]) max_stacks_rcp = get_stack_max(inv, data, is_recipe, panel.rcp[data.rnum])
end end
if usg_normal then if usg_normal then
max_stacks_usg = get_stack_max(data, is_recipe, panel.rcp[data.unum]) max_stacks_usg = get_stack_max(inv, data, is_recipe, panel.rcp[data.unum])
end end
if is_recipe and max_stacks_rcp == 0 then if is_recipe and max_stacks_rcp == 0 then
@ -1454,8 +1578,7 @@ local function get_rcp_extra(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)
@ -1476,16 +1599,16 @@ local function get_favs(fs, data)
local Y = data.yoffset + 0.8 local Y = data.yoffset + 0.8
if data.query_item == item then if data.query_item == item then
fs(fmt("image", X, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, PNG.selected)) fs(fmt("image", X, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, PNG.slot))
end end
fs(fmt("item_image_button", X, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, item, item, "")) fs(fmt("item_image_button", X, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, item, item, ""))
end end
end end
local function get_panels(fs, data) local function get_panels(player, fs, data)
local _title = {name = "title", height = 1.4} local _title = {name = "title", height = 1.4}
local _favs = {name = "favs", height = 2.2} local _favs = {name = "favs", height = 2.23}
local _recipes = {name = "recipes", rcp = data.recipes, height = 3.9} local _recipes = {name = "recipes", rcp = data.recipes, height = 3.9}
local _usages = {name = "usages", rcp = data.usages, height = 3.9} local _usages = {name = "usages", rcp = data.usages, height = 3.9}
local panels = {_title, _recipes, _usages, _favs} local panels = {_title, _recipes, _usages, _favs}
@ -1505,53 +1628,37 @@ local function get_panels(fs, data)
local is_recipe, is_usage = panel.name == "recipes", panel.name == "usages" local is_recipe, is_usage = panel.name == "recipes", panel.name == "usages"
if is_recipe or is_usage then if is_recipe or is_usage then
get_rcp_extra(fs, data, panel, is_recipe, is_usage) get_rcp_extra(player, fs, data, panel, is_recipe, is_usage)
elseif panel.name == "title" then elseif panel.name == "title" then
get_title_fs(fs, data) get_header(fs, data)
elseif panel.name == "favs" then elseif panel.name == "favs" then
get_favs(fs, data) get_favs(fs, data)
end end
end end
end end
local function make_fs(data) local function get_item_list(fs, data, full_height)
local fs = setmetatable({}, { fs(fmt("bg9", 0, 0, data.xoffset, full_height, PNG.bg_full, 10))
__call = function(t, ...)
t[#t + 1] = concat({...})
end
})
data.xoffset = ROWS + 1.04 local filtered = data.filter ~= ""
fs(sprintf([[ fs("box[0.2,0.2;4.55,0.6;#bababa25]", "set_focus[filter]")
formspec_version[%u] fs(sprintf("field[0.3,0.2;%f,0.6;filter;;%s]", filtered and 3.45 or 3.9, ESC(data.filter)))
size[%f,%f] fs("field_close_on_enter[filter;false]")
no_prepend[]
bgcolor[#0000]
]],
MIN_FORMSPEC_VERSION, data.xoffset + (data.query_item and 8 or 0), LINES + 1.7), styles)
fs(fmt("bg9", 0, 0, data.xoffset, LINES + 1.7, PNG.bg_full, 10)) if filtered then
fs(fmt("image_button", 3.75, 0.35, 0.3, 0.3, "", "cancel", ""))
fs(sprintf([[
box[0.2,0.2;4,0.6;#bababa25]
set_focus[filter]
field[0.3,0.2;3.4,0.6;filter;;%s]
field_close_on_enter[filter;false]
]], ESC(data.filter)),
fmt("image_button", 4.25, 0.14, 0.7, 0.7, "", "search", ""))
if data.filter ~= "" then
fs(fmt("image_button", 3.75, 0.35, 0.3, 0.3, PNG.cancel, "cancel", ""))
end end
fs(fmt("image_button", data.xoffset - 3.2, 0.15, 0.7, 0.7, "", "prev_page", ""), fs(fmt("image_button", 4.25, 0.32, 0.35, 0.35, "", "search", ""))
fmt("image_button", data.xoffset - 0.7, 0.15, 0.7, 0.7, "", "next_page", ""))
fs(fmt("image_button", data.xoffset - 2.73, 0.3, 0.35, 0.35, "", "prev_page", ""),
fmt("image_button", data.xoffset - 0.55, 0.3, 0.35, 0.35, "", "next_page", ""))
data.pagemax = max(1, ceil(#data.items / IPP)) data.pagemax = max(1, ceil(#data.items / IPP))
fs(fmt("button", fs(fmt("button",
data.xoffset - 2.53, 0.15, 1.88, 0.7, "pagenum", data.xoffset - 2.4, 0.14, 1.88, 0.7, "pagenum",
sprintf("%s / %u", clr("#ff0", data.pagenum), data.pagemax))) sprintf("%s / %u", clr("#ff0", data.pagenum), data.pagemax)))
if #data.items == 0 then if #data.items == 0 then
@ -1571,28 +1678,46 @@ local function make_fs(data)
if not item then break end if not item then break end
local X = i % ROWS local X = i % ROWS
X = X + (X * 0.08) + 0.2 X = X + (X * 0.1) + 0.2
local Y = (i % IPP - X) / ROWS + 1 local Y = floor((i % IPP - X) / ROWS + 1)
Y = Y + (Y * 0.06) Y = Y + (Y * 0.06) + 1
if data.query_item == item then if data.query_item == item then
fs(fmt("image", X, Y, 1, 1, PNG.selected)) 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
if (data.recipes and #data.recipes > 0) or (data.usages and #data.usages > 0) then local function make_fs(player, data)
get_panels(fs, data) local fs = setmetatable({}, {
__call = function(t, ...)
t[#t + 1] = concat({...})
end
})
data.xoffset = ROWS + 1.2
local full_height = LINES + 1.73
fs(sprintf("formspec_version[%u]size[%f,%f]no_prepend[]bgcolor[#0000]",
MIN_FORMSPEC_VERSION, data.xoffset + (data.query_item and 8 or 0), full_height), styles)
get_item_list(fs, data, full_height)
if data.query_item then
get_panels(player, fs, data)
end end
return concat(fs) return concat(fs)
end end
local show_fs = function(player, name) local function show_fs(player, name)
local data = pdata[name] local data = pdata[name]
show_formspec(name, "craftguide", make_fs(data)) local fs = make_fs(player, data)
show_formspec(name, "craftguide", fs)
end end
craftguide.register_craft_type("digging", { craftguide.register_craft_type("digging", {
@ -1633,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
@ -1680,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.
@ -1785,9 +1927,7 @@ local function get_init_items()
for name in pairs(_preselect) do for name in pairs(_preselect) do
cache_usages(name) cache_usages(name)
end
for name in pairs(_preselect) do
if recipes_cache[name] or usages_cache[name] then if recipes_cache[name] or usages_cache[name] then
init_items[#init_items + 1] = name init_items[#init_items + 1] = name
_select[name] = true _select[name] = true
@ -1822,7 +1962,6 @@ local function init_data(name)
export_counts = {}, export_counts = {},
lang_code = get_lang_code(info), lang_code = get_lang_code(info),
fs_version = get_formspec_version(info), fs_version = get_formspec_version(info),
player = get_player_by_name(name),
} }
end end
@ -1836,7 +1975,6 @@ local function reset_data(data)
data.query_item = nil data.query_item = nil
data.recipes = nil data.recipes = nil
data.usages = nil data.usages = nil
data.show_usages = nil
data.export_rcp = nil data.export_rcp = nil
data.export_usg = nil data.export_usg = nil
data.items = data.items_raw data.items = data.items_raw
@ -1854,13 +1992,31 @@ on_joinplayer(function(player)
end end
end) end)
local function fields(player, _f) on_receive_fields(function(player, formname, _f)
if _f.quit then return end if formname ~= "craftguide" then
return false
end
local name = player:get_player_name() local name = player:get_player_name()
local data = pdata[name] local data = pdata[name]
local sb_rcp, sb_usg = _f.scrbar_rcp, _f.scrbar_usg local sb_rcp, sb_usg = _f.scrbar_rcp, _f.scrbar_usg
if _f.cancel then if _f.quit then
-- Neither the vignette nor hud_flags are available when /craft is used
if data.vignette then
player:hud_change(data.vignette, "text", "")
data.vignette = nil
end
if data.hud_flags then
data.hud_flags.crosshair = true
player:hud_set_flags(data.hud_flags)
data.hud_flags = nil
end
return false
elseif _f.cancel then
reset_data(data) reset_data(data)
elseif _f.prev_recipe or _f.next_recipe then elseif _f.prev_recipe or _f.next_recipe then
@ -1924,6 +2080,22 @@ local function fields(player, _f)
end end
end end
elseif _f.trash then
local inv = player:get_inventory()
if not inv:is_empty("main") then
inv:set_list("main", {})
end
elseif _f.compress then
compress_items(player)
elseif _f.sort_az or _f.sort_za then
sort_itemlist(player, _f.sort_az)
elseif _f.scrbar_inv then
data.scrbar_inv = tonumber(match(_f.scrbar_inv, "%d+"))
return true
elseif (sb_rcp and sub(sb_rcp, 1, 3) == "CHG") or (sb_usg and sub(sb_usg, 1, 3) == "CHG") then elseif (sb_rcp and sub(sb_rcp, 1, 3) == "CHG") or (sb_usg and sub(sb_usg, 1, 3) == "CHG") then
data.scrbar_rcp = sb_rcp and tonum(match(sb_rcp, "%d+")) data.scrbar_rcp = sb_rcp and tonum(match(sb_rcp, "%d+"))
data.scrbar_usg = sb_usg and tonum(match(sb_usg, "%d+")) data.scrbar_usg = sb_usg and tonum(match(sb_usg, "%d+"))
@ -1935,17 +2107,12 @@ local function fields(player, _f)
end end
return true, show_fs(player, name) return true, show_fs(player, name)
end
on_receive_fields(function(player, formname, _f)
if formname == "craftguide" then
fields(player, _f)
end
end) end)
local function on_use(user) local function on_use(user)
local name = user:get_player_name() local name = user:get_player_name()
local data = pdata[name] local data = pdata[name]
if not data then return end
if data.fs_version < MIN_FORMSPEC_VERSION then if data.fs_version < MIN_FORMSPEC_VERSION then
return outdated(name) return outdated(name)
@ -1956,7 +2123,19 @@ local function on_use(user)
search(data) search(data)
end end
show_formspec(name, "craftguide", make_fs(data)) show_fs(user, name)
data.vignette = user:hud_add({
hud_elem_type = "image",
position = {x = 0.5, y = 0.5},
scale = {x = -100, y = -100},
text = "craftguide_vignette.png",
z_index = -0xB00B,
})
data.hud_flags = user:hud_get_flags()
data.hud_flags.crosshair = false
user:hud_set_flags(data.hud_flags)
end end
core.register_craftitem("craftguide:book", { core.register_craftitem("craftguide:book", {
@ -1965,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
}) })
@ -1997,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
}) })
@ -2270,7 +2449,7 @@ on_leaveplayer(function(player)
pdata[name] = nil pdata[name] = nil
end) end)
function craftguide.show(name, item, show_usages) function craftguide.show(name, item)
if not true_str(name) then if not true_str(name) then
return err "craftguide.show(): player name missing" return err "craftguide.show(): player name missing"
end end
@ -2287,7 +2466,7 @@ function craftguide.show(name, item, show_usages)
if not recipes and not usages then if not recipes and not usages then
if not recipes_cache[item] and not usages_cache[item] then if not recipes_cache[item] and not usages_cache[item] then
return false, msg(name, sprintf("%s: %s", return false, msg(name, sprintf("%s: %s",
S"No recipe or usage for this item", get_desc(item))) S"No recipe or usage for this node", clr("#ff0", get_desc(item))))
end end
return false, msg(name, sprintf("%s: %s", return false, msg(name, sprintf("%s: %s",
@ -2316,10 +2495,14 @@ register_command("craft", {
local node = core.get_node(look_at) local node = core.get_node(look_at)
if node.name ~= "air" then if node.name ~= "air" then
local def = reg_items[node.name]
if def then
node_name = node.name node_name = node.name
break break
end end
end end
end
if not node_name then if not node_name then
return false, msg(name, S"No node pointed") return false, msg(name, S"No node pointed")

View File

@ -3,7 +3,7 @@ License of source code
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2015-2020 Jean-Patrick Guerrero and contributors. Copyright (c) 2015-present Jean-Patrick Guerrero and contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -27,10 +27,8 @@ THE SOFTWARE.
Licenses of media (textures) Licenses of media (textures)
---------------------------- ----------------------------
Copyright © Diego Martínez (kaeza): craftguide_*_icon.png (CC BY-SA 3.0)
paramat (CC BY-SA 3.0): paramat (CC BY-SA 3.0):
sfinv_crafting_arrow.png - derived from a texture by BlockMen (CC BY-SA 3.0) craftguide_arrow.png - derived from a texture by BlockMen (CC BY-SA 3.0)
You are free to: You are free to:
Share — copy and redistribute the material in any medium or format. Share — copy and redistribute the material in any medium or format.

View File

@ -53,7 +53,7 @@ Collect items to reveal more recipes=Collecte des items pour révéler plus de r
Show recipe(s) of the pointed node=Affiche les recettes du bloc visé Show recipe(s) of the pointed node=Affiche les recettes du bloc visé
No node pointed=Aucun bloc visé No node pointed=Aucun bloc visé
You don't know a recipe or usage for this item=Vous ne connaissez aucune recette pour ce bloc You don't know a recipe or usage for this item=Vous ne connaissez aucune recette pour ce bloc
No recipe or usage for this item=Aucune recette pour ce bloc No recipe or usage for this node=Aucune recette pour ce bloc
Digging=Destruction Digging=Destruction
Digging (by chance)=Destruction (par chance) Digging (by chance)=Destruction (par chance)
@1 of chance to drop=@1 de chance de tomber @1 of chance to drop=@1 de chance de tomber

View File

@ -53,7 +53,7 @@ Collect items to reveal more recipes=
Show recipe(s) of the pointed node= Show recipe(s) of the pointed node=
No node pointed= No node pointed=
You don't know a recipe or usage for this item= You don't know a recipe or usage for this item=
No recipe or usage for this item= No recipe or usage for this node=
Digging= Digging=
Digging (by chance)= Digging (by chance)=
@1 of chance to drop= @1 of chance to drop=

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB