Compare commits

..

1 Commits
1.10 ... 1.9c

Author SHA1 Message Date
0e90d85423 Fix messages in craft command 2019-10-04 01:08:20 +02:00
6 changed files with 319 additions and 473 deletions

View File

@ -9,7 +9,6 @@ read_globals = {
"vector", "vector",
"string", "string",
"table", "table",
"ItemStack",
} }
globals = { globals = {

52
API.md
View File

@ -35,7 +35,7 @@ craftguide.register_craft({
}) })
``` ```
Recipes can be registered in a Minecraft-like way: Recipes can also be registered in a Minecraft-like way:
```Lua ```Lua
craftguide.register_craft({ craftguide.register_craft({
@ -53,47 +53,6 @@ craftguide.register_craft({
}) })
``` ```
Multiples recipes can also be registered:
```Lua
craftguide.register_craft({
{
result = "default:mese",
items = {
"default:mese_crystal, default:mese_crystal",
"default:mese_crystal, default:mese_crystal",
}
},
{
result = "default:mese 2",
items = {
"default:mese_crystal, default:mese_crystal",
"default:mese_crystal, default:mese_crystal",
"default:mese_crystal, default:mese_crystal",
}
},
big = {
result = "default:mese 4",
items = {
"default:mese_crystal, default:mese_crystal",
"default:mese_crystal, default:mese_crystal",
"default:mese_crystal, default:mese_crystal",
"default:mese_crystal, default:mese_crystal",
}
},
})
```
Recipes can be registered via an URL (HTTP support is required¹):
```Lua
craftguide.register_craft({
url = https://raw.githubusercontent.com/minetest-mods/craftguide/master/test.json
})
```
--- ---
### Recipe filters ### Recipe filters
@ -209,12 +168,3 @@ You can add a stereotype like so:
```Lua ```Lua
craftguide.group_stereotypes.radioactive = "mod:item" craftguide.group_stereotypes.radioactive = "mod:item"
``` ```
#### `craftguide.http_post_data`
If set, the mod will export all the cached recipes and usages in a JSON format
to the given URL (HTTP support is required¹).
---
**¹** Add `craftguide` to the `secure.http_mods` or `secure.trusted_mods` setting in `minetest.conf`.

View File

@ -19,4 +19,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/w7KMS9G.png) ![Preview2](https://i.imgur.com/GVQvufb.png)

549
init.lua
View File

@ -20,17 +20,16 @@ local toolrepair
local progressive_mode = core.settings:get_bool("craftguide_progressive_mode") local progressive_mode = core.settings:get_bool("craftguide_progressive_mode")
local sfinv_only = core.settings:get_bool("craftguide_sfinv_only") and rawget(_G, "sfinv") local sfinv_only = core.settings:get_bool("craftguide_sfinv_only") and rawget(_G, "sfinv")
local http = core.request_http_api()
local reg_items = core.registered_items local reg_items = core.registered_items
local reg_nodes = core.registered_nodes
local reg_tools = core.registered_tools local reg_tools = core.registered_tools
local reg_entities = core.registered_nodes
local reg_aliases = core.registered_aliases local reg_aliases = core.registered_aliases
local reg_craftitems = core.registered_craftitems
local log = core.log local log = core.log
local after = core.after local after = core.after
local clr = core.colorize local clr = core.colorize
local parse_json = core.parse_json
local write_json = core.write_json
local chat_send = core.chat_send_player local chat_send = core.chat_send_player
local show_formspec = core.show_formspec local show_formspec = core.show_formspec
local globalstep = core.register_globalstep local globalstep = core.register_globalstep
@ -88,7 +87,6 @@ local PNG = {
fire = "craftguide_fire.png", fire = "craftguide_fire.png",
book = "craftguide_book.png", book = "craftguide_book.png",
sign = "craftguide_sign.png", sign = "craftguide_sign.png",
selected = "craftguide_selected.png",
} }
local FMT = { local FMT = {
@ -100,7 +98,6 @@ local FMT = {
item_image = "item_image[%f,%f;%f,%f;%s]", item_image = "item_image[%f,%f;%f,%f;%s]",
image_button = "image_button[%f,%f;%f,%f;%s;%s;%s]", image_button = "image_button[%f,%f;%f,%f;%s;%s;%s]",
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.8,0.8;%s;%s;;;false;%s^\\[colorize:yellow:255]",
} }
craftguide.group_stereotypes = { craftguide.group_stereotypes = {
@ -121,13 +118,12 @@ local function msg(name, str)
return chat_send(name, fmt("[craftguide] %s", clr("#FFFF00", str))) return chat_send(name, fmt("[craftguide] %s", clr("#FFFF00", str)))
end end
local function clean_str(str)
local function is_str(x) return match(str, "%S*")
return type(x) == "string"
end end
local function true_str(str) local function is_str(x)
return is_str(str) and str ~= "" return type(x) == "string" and clean_str(x)
end end
local function is_table(x) local function is_table(x)
@ -182,25 +178,26 @@ local function table_eq(T1, T2)
end end
avoid_loops[t1] = t2 avoid_loops[t1] = t2
local t2k, t2kv = {}, {} local t2keys = {}
local t2tablekeys = {}
for k in pairs(t2) do for k in pairs(t2) do
if is_table(k) then if type(k) == "table" then
insert(t2kv, k) insert(t2tablekeys, k)
end end
t2k[k] = true t2keys[k] = true
end end
for k1, v1 in pairs(t1) do for k1, v1 in pairs(t1) do
local v2 = t2[k1] local v2 = t2[k1]
if type(k1) == "table" then if type(k1) == "table" then
local ok local ok
for i = 1, #t2kv do for i = 1, #t2tablekeys do
local tk = t2kv[i] local tk = t2tablekeys[i]
if table_eq(k1, tk) and recurse(v1, t2[tk]) then if table_eq(k1, tk) and recurse(v1, t2[tk]) then
remove(t2kv, i) remove(t2tablekeys, i)
t2k[tk] = nil t2keys[tk] = nil
ok = true ok = true
break break
end end
@ -209,12 +206,12 @@ local function table_eq(T1, T2)
if not ok then return end if not ok then return end
else else
if v2 == nil then return end if v2 == nil then return end
t2k[k1] = nil t2keys[k1] = nil
if not recurse(v1, v2) then return end if not recurse(v1, v2) then return end
end end
end end
if next(t2k) then return end if next(t2keys) then return end
return true return true
end end
@ -252,7 +249,7 @@ end
local craft_types = {} local craft_types = {}
function craftguide.register_craft_type(name, def) function craftguide.register_craft_type(name, def)
if not true_str(name) then if not is_str(name) then
return err("craftguide.register_craft_type(): name missing") return err("craftguide.register_craft_type(): name missing")
end end
@ -268,43 +265,19 @@ function craftguide.register_craft_type(name, def)
end end
function craftguide.register_craft(def) function craftguide.register_craft(def)
local width, c = 0, 0 def.custom = true
def.width = 0
if true_str(def.url) then local c = 0
if not http then
return err("No HTTP support for this mod. " ..
"Add it to the `secure.http_mods` or `secure.trusted_mods` setting.")
end
http.fetch({url = def.url}, function(result)
if result.succeeded then
local t = parse_json(result.data)
if is_table(t) then
return craftguide.register_craft(t)
end
end
end)
return
end
if not is_table(def) or not next(def) then if not is_table(def) or not next(def) then
return err("craftguide.register_craft(): craft definition missing") return err("craftguide.register_craft(): craft definition missing")
end end
if #def > 1 then
for _, v in pairs(def) do
craftguide.register_craft(v)
end
return
end
if def.result then if def.result then
def.output = def.result -- Backward compatibility def.output = def.result -- Backward compatibility
def.result = nil
end end
if not true_str(def.output) then if not is_str(def.output) then
return err("craftguide.register_craft(): output missing") return err("craftguide.register_craft(): output missing")
end end
@ -326,10 +299,10 @@ function craftguide.register_craft(def)
return #a > #b return #a > #b
end) end)
width = #cp[1] def.width = #cp[1]
for i = 1, #def.grid do for i = 1, #def.grid do
while #def.grid[i] < width do while #def.grid[i] < def.width do
def.grid[i] = def.grid[i] .. " " def.grid[i] = def.grid[i] .. " "
end end
end end
@ -346,35 +319,32 @@ function craftguide.register_craft(def)
items[i] = items[i]:gsub(",", ", ") items[i] = items[i]:gsub(",", ", ")
local rlen = #split(items[i], ",") local rlen = #split(items[i], ",")
if rlen > width then if rlen > def.width then
width = rlen def.width = rlen
end end
end end
for i = 1, len do for i = 1, len do
while #split(items[i], ",") < width do while #split(items[i], ",") < def.width do
items[i] = items[i] .. ", " items[i] = items[i] .. ", "
end end
end end
for name in gmatch(concat(items, ","), "[%s%w_:]+") do for name in gmatch(concat(items, ","), "[%s%w_:]+") do
c = c + 1 c = c + 1
def.items[c] = match(name, "%S+") def.items[c] = clean_str(name)
end end
end end
local output = match(def.output, "%S+") local output = clean_str(def.output)
recipes_cache[output] = recipes_cache[output] or {} recipes_cache[output] = recipes_cache[output] or {}
def.custom = true
def.width = width
insert(recipes_cache[output], def) insert(recipes_cache[output], def)
end end
local recipe_filters = {} local recipe_filters = {}
function craftguide.add_recipe_filter(name, f) function craftguide.add_recipe_filter(name, f)
if not true_str(name) then if not is_str(name) then
return err("craftguide.add_recipe_filter(): name missing") return err("craftguide.add_recipe_filter(): name missing")
elseif not is_func(f) then elseif not is_func(f) then
return err("craftguide.add_recipe_filter(): function missing") return err("craftguide.add_recipe_filter(): function missing")
@ -412,7 +382,7 @@ end
local search_filters = {} local search_filters = {}
function craftguide.add_search_filter(name, f) function craftguide.add_search_filter(name, f)
if not true_str(name) then if not is_str(name) then
return err("craftguide.add_search_filter(): name missing") return err("craftguide.add_search_filter(): name missing")
elseif not is_func(f) then elseif not is_func(f) then
return err("craftguide.add_search_filter(): function missing") return err("craftguide.add_search_filter(): function missing")
@ -568,12 +538,10 @@ local function get_recipes(item, data, player)
if not sfinv_only or (sfinv_only and data.show_usages) then if not sfinv_only or (sfinv_only and data.show_usages) then
usages = apply_recipe_filters(usages, player) usages = apply_recipe_filters(usages, player)
if usages and #usages == 0 then return end
end end
local no_usages = not usages or #usages == 0 return recipes, usages
return not no_recipes and recipes or nil,
not no_usages and usages or nil
end end
local function groups_to_items(groups, get_all) local function groups_to_items(groups, get_all)
@ -660,11 +628,6 @@ local function get_tooltip(item, info)
tooltip = add(S("Repairable by step of @1", clr("yellow", toolrepair .. "%"))) tooltip = add(S("Repairable by step of @1", clr("yellow", toolrepair .. "%")))
end end
if info.rarity then
local chance = (1 / info.rarity) * 100
tooltip = add(S("@1 of chance to drop", clr("yellow", chance .. "%")))
end
return fmt("tooltip[%s;%s]", item, ESC(tooltip)) return fmt("tooltip[%s;%s]", item, ESC(tooltip))
end end
@ -692,7 +655,7 @@ local function get_output_fs(fs, L)
end end
end end
local arrow_X = L.rightest + (L._btn_size or 1.1) local arrow_X = L.rightest + (L.s_btn_size or 1.1)
local output_X = arrow_X + 0.9 local output_X = arrow_X + 0.9
fs[#fs + 1] = fmt(FMT.image, fs[#fs + 1] = fmt(FMT.image,
@ -705,29 +668,27 @@ local function get_output_fs(fs, L)
1.1, 1.1, PNG.fire) 1.1, 1.1, PNG.fire)
else else
local item = L.recipe.output local item = L.recipe.output
local name = match(item, "%S*") local name = clean_str(item)
fs[#fs + 1] = fmt(FMT.item_image_button, fs[#fs + 1] = fmt(FMT.item_image_button,
output_X, YOFFSET + (sfinv_only and 0.7 or 0) + L.spacing, output_X, YOFFSET + (sfinv_only and 0.7 or 0) + L.spacing,
1.1, 1.1, item, ESC(name), "") 1.1, 1.1, item, ESC(name), "")
if CORE_VERSION >= 510 then
fs[#fs + 1] = fmt(FMT.image, fs[#fs + 1] = fmt(FMT.image,
output_X, YOFFSET + (sfinv_only and 0.7 or 0) + L.spacing, output_X, YOFFSET + (sfinv_only and 0.7 or 0) + L.spacing,
1.1, 1.1, PNG.selected) 1.1, 1.1, "craftguide_selected.png")
local burntime = fuel_cache[name]
local repair = repairable(name)
if burntime or repair then
fs[#fs + 1] = get_tooltip(name, {
burntime = burntime,
repair = repair,
})
end end
local infos = { if burntime then
burntime = fuel_cache[name],
repair = repairable(name),
rarity = L.rarity,
}
if next(infos) then
fs[#fs + 1] = get_tooltip(name, infos)
end
if infos.burntime then
fs[#fs + 1] = fmt(FMT.image, fs[#fs + 1] = fmt(FMT.image,
output_X + 1, YOFFSET + (sfinv_only and 0.7 or 0.1) + L.spacing, output_X + 1, YOFFSET + (sfinv_only and 0.7 or 0.1) + L.spacing,
0.6, 0.4, PNG.arrow) 0.6, 0.4, PNG.arrow)
@ -739,12 +700,77 @@ local function get_output_fs(fs, L)
end end
end end
local function get_grid_fs(fs, rcp, spacing) local function pretty_wrap(str, limit)
if not rcp then return end return #str > limit + 3 and sub(str, 1, limit) .. "..." or str
end
local function get_itemdef_fs(fs, L)
fs[#fs + 1] = CORE_VERSION >= 510 and
fmt("background9[8.1,%f;6.6,2.19;%s;false;%d]",
L.y, PNG.bg_full, 10) or
fmt("background[8.1,%f;6.6,2.19;%s;false]", L.y, PNG.bg_full)
local def = reg_items[L.item]
local namestr = fmt("%s (%s)", pretty_wrap(get_desc(L.item), 25), L.item)
local typestr
if reg_nodes[L.item] then
typestr = fmt("%s (%s)", ESC(S("Node")), def.drawtype)
elseif reg_entities[L.item] then
typestr = ESC(S("Entity"))
elseif reg_craftitems[L.item] then
typestr = ESC(S("Craftitem"))
elseif reg_tools[L.item] then
typestr = ESC(S("Tool"))
end
local groupstr
for k, v in pairs(def.groups or {}) do
groupstr = (groupstr or "") .. fmt("%s(%d), ", pretty_wrap(k, 13), v)
end
groupstr = groupstr and sub(groupstr, 1, -3)
local specs = {
ESC(S("Name")),
ESC(S("Type")),
ESC(S("Groups")),
}
local tstr = ""
for i = 1, #specs do
tstr = tstr .. "#6389FF," .. specs[i] .. ",#FFFFFF,%s,"
end
tstr = sub(tstr, 1, -2)
fs[#fs + 1] = [[
tableoptions[background=#00000000;highlight=#00000000;border=false]
tablecolumns[color;text]
]]
fs[#fs + 1] = fmt("table[8.1,%f;6.3,1.8;itemdef;" .. tstr .. ";0]",
L.y + 0.08,
namestr,
ESC(typestr or S("Unknown")),
ESC(groupstr or S("None")))
end
local function get_info_fs(data, fs)
local t = {recipes = data.recipes, usages = data.usages}
local infonum = 0
local last_y
if sfinv_only then
t = data.show_usages and {usages = data.usages} or {recipes = data.recipes}
end
for k, v in pairs(t) do
infonum = infonum + 1
local spacing = (infonum - 1) * 3.6
last_y = -0.2 + infonum * 3.6
local rcp = k == "recipes" and v[data.rnum] or v[data.unum]
local width = rcp.width or 1 local width = rcp.width or 1
local replacements = rcp.replacements local replacements = rcp.replacements
local rarity = rcp.rarity
local rightest, btn_size, _btn_size = 0, 1.1
local cooktime, shapeless local cooktime, shapeless
if rcp.type == "cooking" then if rcp.type == "cooking" then
@ -756,11 +782,39 @@ local function get_grid_fs(fs, rcp, spacing)
end end
local rows = ceil(maxn(rcp.items) / width) local rows = ceil(maxn(rcp.items) / width)
local rightest, btn_size, s_btn_size = 0, 1.1
if not sfinv_only then
fs[#fs + 1] = CORE_VERSION >= 510 and
fmt("background9[8.1,%f;6.6,3.5;%s;false;%d]",
-0.2 + spacing, PNG.bg_full, 10) or
fmt("background[8.1,%f;6.6,3.5;%s;false]",
-0.2 + spacing, PNG.bg_full)
end
local btn_lab
if (not sfinv_only and k == "recipes") or
(sfinv_only and not data.show_usages) then
btn_lab = ESC(S("Recipe @1 of @2", data.rnum, #v))
elseif not sfinv_only or (sfinv_only and data.show_usages) then
btn_lab = ESC(S("Usage @1 of @2", data.unum, #v))
end
if sfinv_only then
btn_lab = data.show_usages and
ESC(S("Usage @1 of @2", data.rnum, #v)) or
ESC(S("Recipe @1 of @2", data.rnum, #v))
end
fs[#fs + 1] = fmt(FMT.button,
XOFFSET + (sfinv_only and 1.98 or 1.12),
YOFFSET + (sfinv_only and 1.9 or 1.2 + spacing),
2.2, 1, "alternate_" .. (k == "recipes" and "recipe" or "usage"), btn_lab)
if width > WH_LIMIT or rows > WH_LIMIT then if width > WH_LIMIT or rows > WH_LIMIT then
fs[#fs + 1] = fmt(FMT.label, fs[#fs + 1] = fmt(FMT.label,
XOFFSET + (sfinv_only and -1.5 or -1.6), sfinv_only and 2 or 3, 7,
YOFFSET + (sfinv_only and 0.5 or spacing),
ESC(S("Recipe's too big to be displayed (@1x@2)", width, rows))) ESC(S("Recipe's too big to be displayed (@1x@2)", width, rows)))
return concat(fs) return concat(fs)
@ -784,12 +838,12 @@ local function get_grid_fs(fs, rcp, spacing)
btn_size = width > rows and btn_size = width > rows and
(3.5 + (xof * 2)) / width or (3.5 + (yof * 2)) / rows (3.5 + (xof * 2)) / width or (3.5 + (yof * 2)) / rows
_btn_size = btn_size s_btn_size = btn_size
X = (btn_size * ((i - 1) % width) + XOFFSET - X = (btn_size * ((i - 1) % width) + XOFFSET -
(sfinv_only and 2.83 or 0.5)) * (0.83 - (x_y / 5)) (sfinv_only and 2.83 or 0.5)) * (0.83 - (x_y / 5))
Y = (btn_size * floor((i - 1) / width) + Y = (btn_size * floor((i - 1) / width) +
(sfinv_only and 5.81 or 5.5) + x_y) * (0.86 - (x_y / 5)) (sfinv_only and 5.81 or 4) + x_y) * (0.86 - (x_y / 5))
end end
if X > rightest then if X > rightest then
@ -819,24 +873,27 @@ local function get_grid_fs(fs, rcp, spacing)
fs[#fs + 1] = fmt(FMT.item_image_button, fs[#fs + 1] = fmt(FMT.item_image_button,
X, Y + (sfinv_only and 0.7 or 0), X, Y + (sfinv_only and 0.7 or 0),
btn_size, btn_size, item, match(item, "%S*"), ESC(label)) btn_size, btn_size, item, clean_str(item), ESC(label))
local infos = { local infos = {
unknown = reg_items[item] and nil, unknown = not reg_items[item],
groups = groups, groups = groups,
burntime = fuel_cache[item], burntime = fuel_cache[item],
cooktime = cooktime, cooktime = cooktime,
replace = replace, replace = replace,
} }
if next(infos) then for _, info in pairs(infos) do
if info then
fs[#fs + 1] = get_tooltip(item, infos) fs[#fs + 1] = get_tooltip(item, infos)
break
end
end end
if CORE_VERSION >= 510 and not large_recipe then if not large_recipe then
fs[#fs + 1] = fmt(FMT.image, fs[#fs + 1] = fmt(FMT.image,
X, Y + (sfinv_only and 0.7 or 0), X, Y + (sfinv_only and 0.7 or 0),
btn_size, btn_size, PNG.selected) btn_size, btn_size, "craftguide_selected.png")
end end
end end
@ -849,71 +906,16 @@ local function get_grid_fs(fs, rcp, spacing)
shapeless = shapeless, shapeless = shapeless,
rightest = rightest, rightest = rightest,
btn_size = btn_size, btn_size = btn_size,
_btn_size = _btn_size, s_btn_size = s_btn_size,
spacing = spacing, spacing = spacing,
rarity = rarity,
}) })
end
local function get_panels(data, fs)
local panels = {recipes = data.recipes or {}, usages = data.usages or {}}
local x = 0.33
if sfinv_only then
panels = data.show_usages and
{usages = data.usages} or {recipes = data.recipes}
end end
for k, v in pairs(panels) do
x = x + 1
local spacing = (x - 1) * 3.6
if not sfinv_only then if not sfinv_only then
fs[#fs + 1] = CORE_VERSION >= 510 and get_itemdef_fs(fs, {
fmt("background9[8.1,%f;6.6,3.5;%s;false;%d]", item = data.query_item,
-0.2 + spacing, PNG.bg_full, 10) or y = last_y,
fmt("background[8.1,%f;6.6,3.5;%s;false]", })
-0.2 + spacing, PNG.bg_full)
end
local btn_lab
if not sfinv_only and #v == 0 then
btn_lab = clr("red", k == "recipes" and
ESC(S("No recipes")) or ESC(S("No usages")))
elseif (not sfinv_only and k == "recipes") or
(sfinv_only and not data.show_usages) then
btn_lab = ESC(S("Recipe @1 of @2", data.rnum, #v))
elseif not sfinv_only or (sfinv_only and data.show_usages) then
btn_lab = ESC(S("Usage @1 of @2", data.unum, #v))
elseif sfinv_only then
btn_lab = data.show_usages and
ESC(S("Usage @1 of @2", data.unum, #v)) or
ESC(S("Recipe @1 of @2", data.rnum, #v))
end
fs[#fs + 1] = fmt(FMT.label,
XOFFSET + (sfinv_only and 2.3 or 1.6),
YOFFSET + (sfinv_only and 2.2 or 1.5 + spacing),
btn_lab)
if #v > 1 then
local btn_suffix = k == "recipes" and "recipe" or "usage"
local x_arrow = XOFFSET + (sfinv_only and 1.7 or 1)
local y_arrow = YOFFSET + (sfinv_only and 2.1 or 1.4 + spacing)
fs[#fs + 1] = fmt(FMT.arrow .. FMT.arrow,
x_arrow, y_arrow, PNG.prev,
fmt("prev_%s", btn_suffix), PNG.prev,
x_arrow + 1.8, y_arrow, PNG.next,
fmt("next_%s", btn_suffix), PNG.next)
end
local rcp = k == "recipes" and v[data.rnum] or v[data.unum]
get_grid_fs(fs, rcp, spacing)
end end
end end
@ -953,15 +955,14 @@ local function make_formspec(name)
sfinv_only and 2.6 or 2.54, PNG.search, PNG.search, sfinv_only and 2.6 or 2.54, PNG.search, PNG.search,
sfinv_only and 3.3 or 3.25, PNG.clear, PNG.clear) sfinv_only and 3.3 or 3.25, PNG.clear, PNG.clear)
fs[#fs + 1] = fmt("label[%f,%f;%s / %u]", fs[#fs + 1] = fmt([[
sfinv_only and 6.35 or (ROWS * 7.85) / 11, image_button[%f,-0.05;0.8,0.8;%s;prev;;;false;%s^\[colorize:yellow:255]
0.06, clr("yellow", data.pagenum), data.pagemax) label[%f,%f;%s / %u]
image_button[%f,-0.05;0.8,0.8;%s;next;;;false;%s^\[colorize:yellow:255]
fs[#fs + 1] = fmt(FMT.arrow .. FMT.arrow, ]],
sfinv_only and 5.45 or (ROWS * 6.83) / 11, sfinv_only and 5.45 or (ROWS * 6.83) / 11, PNG.prev, PNG.prev,
-0.05, PNG.prev, "prev_page", PNG.prev, sfinv_only and 6.35 or (ROWS * 7.85) / 11, 0.06, clr("yellow", data.pagenum), data.pagemax,
sfinv_only and 7.2 or (ROWS * 8.75) / 11, sfinv_only and 7.2 or (ROWS * 8.75) / 11, PNG.next, PNG.next)
-0.05, PNG.next, "next_page", PNG.next)
if #data.items == 0 then if #data.items == 0 then
local no_item = S("No item to show") local no_item = S("No item to show")
@ -989,16 +990,16 @@ local function make_formspec(name)
Y - (Y * 0.1) - 0.1, Y - (Y * 0.1) - 0.1,
1, 1, item, item) 1, 1, item, item)
if CORE_VERSION >= 510 and data.query_item == item then if data.query_item == item then
fs[#fs + 1] = fmt(FMT.image, fs[#fs + 1] = fmt(FMT.image,
X - (X * (sfinv_only and 0.12 or 0.14)) - 0.05, X - (X * (sfinv_only and 0.12 or 0.14)) - 0.05,
Y - (Y * 0.1) - 0.1, Y - (Y * 0.1) - 0.1,
1, 1, PNG.selected) 1, 1, "craftguide_selected.png")
end end
end end
if (data.recipes and #data.recipes > 0) or (data.usages and #data.usages > 0) then if (data.recipes and #data.recipes > 0) or (data.usages and #data.usages > 0) then
get_panels(data, fs) get_info_fs(data, fs)
end end
return concat(fs) return concat(fs)
@ -1027,16 +1028,6 @@ craftguide.add_search_filter("groups", function(item, groups)
return has_groups return has_groups
end) end)
craftguide.register_craft_type("digging", {
description = ESC(S("Digging")),
icon = "default_tool_steelpick.png",
})
craftguide.register_craft_type("digging_chance", {
description = ESC(S("Digging Chance")),
icon = "default_tool_mesepick.png",
})
local function search(data) local function search(data)
local filter = data.filter local filter = data.filter
@ -1111,9 +1102,9 @@ core.register_craft = function(def)
toolrepair = def.additional_wear * -100 toolrepair = def.additional_wear * -100
end end
local output = def.output or (true_str(def.recipe) and def.recipe) or nil local output = def.output or is_str(def.recipe)
if not output then return end if not output then return end
output = {match(output, "%S+")} output = {clean_str(output)}
local groups local groups
@ -1169,92 +1160,34 @@ core.register_craft = function(def)
end end
end end
local function handle_drops_table(name, drop) local function show_item(def)
-- Code borrowed and modified from unified_inventory return not (def.groups.not_in_craft_guide == 1 or
-- https://github.com/minetest-mods/unified_inventory/blob/master/api.lua def.groups.not_in_creative_inventory == 1) and
local drop_sure, drop_maybe = {}, {} def.description and def.description ~= ""
local drop_items = drop.items or {}
local max_items_left = drop.max_items
local max_start = true
for i = 1, #drop_items do
if max_items_left and max_items_left <= 0 then break end
local di = drop_items[i]
for j = 1, #di.items do
local dstack = ItemStack(di.items[j])
local dname = dstack:get_name()
if not dstack:is_empty() and dname ~= name then
local dcount = dstack:get_count()
if #di.items == 1 and di.rarity == 1 and max_start then
if not drop_sure[dname] then
drop_sure[dname] = 0
end
drop_sure[dname] = drop_sure[dname] + dcount
if max_items_left then
max_items_left = max_items_left - 1
if max_items_left <= 0 then break end
end
else
if max_items_left then
max_start = false
end
if not drop_maybe[dname] then
drop_maybe[dname] = {}
end
if not drop_maybe[dname].output then
drop_maybe[dname].output = 0
end
drop_maybe[dname] = {
output = drop_maybe[dname].output + dcount,
rarity = di.rarity,
}
end
end
end
end
for item, count in pairs(drop_sure) do
craftguide.register_craft({
type = "digging",
items = {name},
output = fmt("%s %u", item, count),
})
end
for item, data in pairs(drop_maybe) do
craftguide.register_craft({
type = "digging_chance",
items = {name},
output = fmt("%s %u", item, data.output),
rarity = data.rarity,
})
end
end end
local function register_drops(name, def) local function get_init_items()
local drop = def.drop local hash, c = {}, 0
local dstack = ItemStack(drop) for name, def in pairs(reg_items) do
if show_item(def) then
if not dstack:is_empty() and dstack:get_name() ~= name then if not fuel_cache[name] then
craftguide.register_craft({ cache_fuel(name)
type = "digging", end
items = {name},
output = drop, if not recipes_cache[name] then
}) cache_recipes(name)
elseif is_table(drop) then end
handle_drops_table(name, drop)
cache_usages(name)
if recipes_cache[name] or usages_cache[name] then
c = c + 1
init_items[c] = name
hash[name] = true
end
end
end end
end
local function handle_aliases(hash)
for oldname, newname in pairs(reg_aliases) do for oldname, newname in pairs(reg_aliases) do
local recipes = recipes_cache[oldname] local recipes = recipes_cache[oldname]
if recipes then if recipes then
@ -1285,54 +1218,12 @@ local function handle_aliases(hash)
end end
if recipes_cache[oldname] and not hash[newname] then if recipes_cache[oldname] and not hash[newname] then
init_items[#init_items + 1] = newname c = c + 1
end init_items[c] = newname
end
end
local function show_item(def)
return not (def.groups.not_in_craft_guide == 1 or
def.groups.not_in_creative_inventory == 1) and
def.description and def.description ~= ""
end
local function get_init_items()
local hash = {}
for name, def in pairs(reg_items) do
if show_item(def) then
if not fuel_cache[name] then
cache_fuel(name)
end
if not recipes_cache[name] then
cache_recipes(name)
end
cache_usages(name)
register_drops(name, def)
if recipes_cache[name] or usages_cache[name] then
init_items[#init_items + 1] = name
hash[name] = true
end
end end
end end
handle_aliases(hash)
sort(init_items) sort(init_items)
if http and true_str(craftguide.http_post_data) then
local post_data = {
recipes = recipes_cache,
usages = usages_cache,
fuel = fuel_cache,
}
http.fetch_async({
url = craftguide.http_post_data,
post_data = write_json(post_data),
})
end
end end
local function init_data(name) local function init_data(name)
@ -1374,17 +1265,24 @@ local function fields(player, _f)
if _f.clear then if _f.clear then
reset_data(data) reset_data(data)
return true, show_fs(player, name) show_fs(player, name)
return true
elseif _f.prev_recipe or _f.next_recipe then elseif _f.alternate_recipe then
local num = data.rnum + (_f.prev_recipe and -1 or 1) if #data.recipes == 1 then return end
data.rnum = data.recipes[num] and num or (_f.prev_recipe and #data.recipes or 1) local num_next = data.rnum + 1
return true, show_fs(player, name) data.rnum = data.recipes[num_next] and num_next or 1
elseif _f.prev_usage or _f.next_usage then show_fs(player, name)
local num = data.unum + (_f.prev_usage and -1 or 1) return true
data.unum = data.usages[num] and num or (_f.prev_usage and #data.usages or 1)
return true, show_fs(player, name) elseif _f.alternate_usage then
if #data.usages == 1 then return end
local num_next = data.unum + 1
data.unum = data.usages[num_next] and num_next or 1
show_fs(player, name)
return true
elseif (_f.key_enter_field == "filter" or _f.search) and _f.filter ~= "" then elseif (_f.key_enter_field == "filter" or _f.search) and _f.filter ~= "" then
local str = lower(_f.filter) local str = lower(_f.filter)
@ -1394,11 +1292,12 @@ local function fields(player, _f)
data.pagenum = 1 data.pagenum = 1
search(data) search(data)
return true, show_fs(player, name) show_fs(player, name)
return true
elseif _f.prev_page or _f.next_page then elseif _f.prev or _f.next then
if data.pagemax == 1 then return end if data.pagemax == 1 then return end
data.pagenum = data.pagenum - (_f.prev_page and 1 or -1) data.pagenum = data.pagenum - (_f.prev and 1 or -1)
if data.pagenum > data.pagemax then if data.pagenum > data.pagemax then
data.pagenum = 1 data.pagenum = 1
@ -1406,7 +1305,8 @@ local function fields(player, _f)
data.pagenum = data.pagemax data.pagenum = data.pagemax
end end
return true, show_fs(player, name) show_fs(player, name)
return true
else else
local item local item
for field in pairs(_f) do for field in pairs(_f) do
@ -1439,7 +1339,8 @@ local function fields(player, _f)
data.rnum = 1 data.rnum = 1
data.unum = 1 data.unum = 1
return true, show_fs(player, name) show_fs(player, name)
return true
end end
end end
@ -1833,7 +1734,7 @@ on_leaveplayer(function(player)
end) end)
function craftguide.show(name, item, show_usages) function craftguide.show(name, item, show_usages)
if not true_str(name)then if not is_str(name) then
return err("craftguide.show(): player name missing") return err("craftguide.show(): player name missing")
end end

View File

@ -5,8 +5,6 @@ Crafting Guide=
Crafting Guide Sign= Crafting Guide Sign=
Usage @1 of @2= Usage @1 of @2=
Recipe @1 of @2= Recipe @1 of @2=
No recipes=
No usages=
Burning time: @1= Burning time: @1=
Cooking time: @1= Cooking time: @1=
Replaced by @1 on smelting= Replaced by @1 on smelting=
@ -23,6 +21,12 @@ 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 item=
Digging= Node=
Digging Chance= Entity=
@1 of chance to drop= Craftitem=
Tool=
Name=
Type=
Groups=
Unknown=
None=

View File

@ -1,8 +0,0 @@
{
"items": [
"default:stone, default:stone, default:stone",
"default:stone, , default:stone",
"default:stone, default:stone, default:stone"
],
"result": "default:cobble 16"
}