Compare commits

..

24 Commits
1.8 ... 1.8.1

Author SHA1 Message Date
a50a99836a Fix version number check 2019-09-29 21:17:16 +02:00
e2134e479e Delete description file 2019-09-29 20:39:31 +02:00
3320fbdd6b Full backward compat with MT 0.4.17 2019-09-29 20:30:47 +02:00
19fb5e2691 Check compat for background[] 2019-09-29 17:23:03 +02:00
9dd63cd83a Fixed comment 2019-09-29 15:28:53 +02:00
07820fa37c Re-add accidentally removed 2019-09-29 15:24:04 +02:00
29f87f2607 Put the page number color back 2019-09-29 15:20:21 +02:00
aef1fe0dc6 Fix non-shown aliased recipes 2019-09-29 15:16:41 +02:00
22ff82cc89 Merge pull request #90 from h4ml3t/Italian
Add Italian locale
2019-09-29 13:41:11 +02:00
dd98cb2cb3 Italian locale 2019-09-29 13:30:22 +02:00
f184341663 String checking 2019-09-25 16:22:38 +02:00
3f9d7bc12d Table check 2019-09-25 12:44:49 +02:00
60b09a27f7 Ensure that no fuel usages are not shown 2019-09-19 13:38:07 +02:00
a936452e21 Fix non-shown recipes 2019-09-18 20:09:03 +02:00
768e06e2d0 why the hell the page number not colorized anymore? 2019-09-16 12:56:04 +02:00
732535c9da Another attempt to fix nil crash 2019-09-16 12:33:28 +02:00
7a8b8d19df Fix possible nil crash 2019-09-15 22:39:08 +02:00
9dcccadfc2 Minor fix 2019-09-12 13:10:31 +02:00
7c891ff2b6 Small fix for custom recipe 2019-09-11 19:39:49 +02:00
06bef9777a Minor cleaning 2019-09-11 17:25:29 +02:00
738c2140a7 Show itemstring for unknown item 2019-09-11 16:35:56 +02:00
2ffef6794a Do not require to specify width in custom recipes 2019-09-11 16:28:37 +02:00
fb1b0cf869 Notification success: do not depend on dtime 2019-09-11 13:43:13 +02:00
59b806c9c4 Progressive: Update items in sfinv without page change 2019-09-11 12:25:28 +02:00
5 changed files with 365 additions and 212 deletions

18
API.md
View File

@ -19,12 +19,22 @@ craftguide.register_craft_type("digging", {
```Lua ```Lua
craftguide.register_craft({ craftguide.register_craft({
type = "digging", type = "digging",
width = 1,
result = "default:cobble 2", result = "default:cobble 2",
items = {"default:stone"}, items = {"default:stone"},
}) })
``` ```
```Lua
craftguide.register_craft({
result = "default:cobble 16",
items = {
"default:stone, default:stone, default:stone",
"default:stone, , default:stone",
"default:stone, default:stone, default:stone",
}
})
```
Recipes can also be registered in a Minecraft-like way: Recipes can also be registered in a Minecraft-like way:
```Lua ```Lua
@ -72,6 +82,10 @@ craftguide.add_recipe_filter("Hide secretstuff", function(recipes)
end) end)
``` ```
#### `craftguide.set_recipe_filter(name, function(recipe, player))`
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.
@ -160,7 +174,7 @@ craftguide.group_stereotypes.radioactive = "mod:item"
You can set a custom background theme by overriding this variable: You can set a custom background theme by overriding this variable:
```Lua ```Lua
craftguide.background = "<file_name.png>:<middle>" craftguide.background = "<file_name.png>#<middle>"
``` ```

View File

@ -6,7 +6,7 @@
This crafting guide is a blue book named *"Crafting Guide"* or a wooden sign. This crafting guide is a blue book named *"Crafting Guide"* or a wooden sign.
This crafting guide features a **progressive mode**. This crafting guide features a **progressive mode**.
The progressive 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` is also integrated in `sfinv` (Minetest Game inventory). To enable it:
@ -16,5 +16,7 @@ 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).
Love this mod? Donations are appreciated: https://www.paypal.me/jpg84240
![Preview2](https://i.imgur.com/oGSvbTW.png)
![Preview2](https://i.imgur.com/IbexMwQ.png)

View File

@ -1,2 +0,0 @@
The most comprehensive Crafting Guide
on Minetest.

528
init.lua
View File

@ -1,5 +1,12 @@
craftguide = {} craftguide = {}
local p = 0
local CORE_VERSION = core.get_version().string:match("[^%-]*"):gsub("%.", function(a)
p = p + 1
return p == 3 and a or ""
end)
CORE_VERSION = tonumber(CORE_VERSION)
-- Caches -- Caches
local pdata = {} local pdata = {}
local init_items = {} local init_items = {}
@ -7,6 +14,7 @@ local searches = {}
local recipes_cache = {} local recipes_cache = {}
local usages_cache = {} local usages_cache = {}
local fuel_cache = {} local fuel_cache = {}
local alias_cache = {}
local toolrepair local toolrepair
@ -22,16 +30,26 @@ local show_formspec = core.show_formspec
local globalstep = core.register_globalstep local globalstep = core.register_globalstep
local on_shutdown = core.register_on_shutdown local on_shutdown = core.register_on_shutdown
local get_players = core.get_connected_players local get_players = core.get_connected_players
local get_craft_result = core.get_craft_result
local on_joinplayer = core.register_on_joinplayer local on_joinplayer = core.register_on_joinplayer
local get_all_recipes = core.get_all_craft_recipes
local register_command = core.register_chatcommand local register_command = core.register_chatcommand
local get_player_by_name = core.get_player_by_name local get_player_by_name = core.get_player_by_name
local slz, dslz = core.serialize, core.deserialize
local on_mods_loaded = core.register_on_mods_loaded local on_mods_loaded = core.register_on_mods_loaded
local on_leaveplayer = core.register_on_leaveplayer local on_leaveplayer = core.register_on_leaveplayer
local serialize, deserialize = core.serialize, core.deserialize
local on_receive_fields = core.register_on_player_receive_fields local on_receive_fields = core.register_on_player_receive_fields
local ESC = core.formspec_escape local ESC = core.formspec_escape
local S = core.get_translator("craftguide") local S = CORE_VERSION >= 500 and core.get_translator("craftguide") or
function(...)
local args, i = {...}, 1
return args[1]:gsub("@%d+", function()
i = i + 1
return args[i]
end)
end
local maxn, sort, concat, copy, insert = local maxn, sort, concat, copy, insert =
table.maxn, table.sort, table.concat, table.copy, table.insert table.maxn, table.sort, table.concat, table.copy, table.insert
@ -52,20 +70,18 @@ local WH_LIMIT = 8
local XOFFSET = sfinv_only and 3.83 or 4.66 local XOFFSET = sfinv_only and 3.83 or 4.66
local YOFFSET = sfinv_only and 6 or 6.6 local YOFFSET = sfinv_only and 6 or 6.6
local DEV_CORE = sub(core.get_version().string, -3) == "dev" craftguide.background = "craftguide_bg_full.png#10"
craftguide.background = "craftguide_bg_full.png:10"
local PNG = { local PNG = {
bg = "craftguide_bg.png", bg = "craftguide_bg.png",
search = "craftguide_search_icon.png", search = "craftguide_search_icon.png",
clear = "craftguide_clear_icon.png", clear = "craftguide_clear_icon.png",
prev = "craftguide_next_icon.png^\\[transformFX", prev = "craftguide_next_icon.png^\\[transformFX",
next = "craftguide_next_icon.png", next = "craftguide_next_icon.png",
arrow = "craftguide_arrow.png", arrow = "craftguide_arrow.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",
} }
local FMT = { local FMT = {
@ -80,12 +96,12 @@ local FMT = {
} }
craftguide.group_stereotypes = { craftguide.group_stereotypes = {
wool = "wool:white", dye = "dye:white",
dye = "dye:white", wool = "wool:white",
coal = "default:coal_lump",
vessel = "vessels:glass_bottle",
flower = "flowers:dandelion_yellow",
water_bucket = "bucket:bucket_water", water_bucket = "bucket:bucket_water",
vessel = "vessels:glass_bottle",
coal = "default:coal_lump",
flower = "flowers:dandelion_yellow",
mesecon_conductor_craftable = "mesecons:wire_00000000_off", mesecon_conductor_craftable = "mesecons:wire_00000000_off",
} }
@ -117,12 +133,16 @@ local function table_replace(t, val, new)
end end
end end
local function is_str(x) local function err(str)
return type(x) == "string" return log("error", str)
end end
local function is_num(x) local function clean_str(str)
return type(x) == "number" return match(str, "%S*")
end
local function is_str(x)
return type(x) == "string" and clean_str(x)
end end
local function is_table(x) local function is_table(x)
@ -140,8 +160,8 @@ end
local craft_types = {} local craft_types = {}
function craftguide.register_craft_type(name, def) function craftguide.register_craft_type(name, def)
if not is_str(name) or name == "" then if not is_str(name) then
return log("error", "craftguide.register_craft_type(): name missing") return err("craftguide.register_craft_type(): name missing")
end end
if not is_str(def.description) then if not is_str(def.description) then
@ -155,36 +175,36 @@ function craftguide.register_craft_type(name, def)
craft_types[name] = def craft_types[name] = def
end end
local function clean_name(item)
return match(item, "%S+")
end
function craftguide.register_craft(def) function craftguide.register_craft(def)
def.custom = true
def.width = 0
local c = 0
if not is_table(def) or not next(def) then if not is_table(def) or not next(def) then
return log("error", "craftguide.register_craft(): craft definition missing") return err("craftguide.register_craft(): craft definition missing")
end end
if def.result then if def.result then
def.output = def.result -- Backward compatibility def.output = def.result -- Backward compatibility
end end
if not is_str(def.output) or def.output == "" then if not is_str(def.output) then
return log("error", "craftguide.register_craft(): output missing") return err("craftguide.register_craft(): output missing")
end end
if not is_table(def.items) then if not is_table(def.items) then
def.items = {} def.items = {}
end end
if not is_num(def.width) then
def.width = 0
end
if def.grid then if def.grid then
if not is_table(def.grid) then if not is_table(def.grid) then
def.grid = {} def.grid = {}
end end
if not is_table(def.key) then
def.key = {}
end
local cp = copy(def.grid) local cp = copy(def.grid)
sort(cp, function(a, b) sort(cp, function(a, b)
return #a > #b return #a > #b
@ -198,14 +218,36 @@ function craftguide.register_craft(def)
end end
end end
local c = 1
for symbol in gmatch(concat(def.grid), ".") do for symbol in gmatch(concat(def.grid), ".") do
def.items[c] = def.key[symbol]
c = c + 1 c = c + 1
def.items[c] = def.key[symbol]
end
else
local items, len = def.items, #def.items
def.items = {}
for i = 1, len do
items[i] = items[i]:gsub(",", ", ")
local rlen = #split(items[i], ",")
if rlen > def.width then
def.width = rlen
end
end
for i = 1, len do
while #split(items[i], ",") < def.width do
items[i] = items[i] .. ", "
end
end
for name in gmatch(concat(items, ","), "[%s%w_:]+") do
c = c + 1
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 {}
insert(recipes_cache[output], def) insert(recipes_cache[output], def)
end end
@ -213,15 +255,25 @@ end
local recipe_filters = {} local recipe_filters = {}
function craftguide.add_recipe_filter(name, f) function craftguide.add_recipe_filter(name, f)
if not is_str(name) or name == "" then if not is_str(name) then
return log("error", "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 log("error", "craftguide.add_recipe_filter(): function missing") return err("craftguide.add_recipe_filter(): function missing")
end end
recipe_filters[name] = f recipe_filters[name] = f
end end
function craftguide.set_recipe_filter(name, f)
if not is_str(name) then
return err("craftguide.set_recipe_filter(): name missing")
elseif not is_func(f) then
return err("craftguide.set_recipe_filter(): function missing")
end
recipe_filters = {[name] = f}
end
function craftguide.remove_recipe_filter(name) function craftguide.remove_recipe_filter(name)
recipe_filters[name] = nil recipe_filters[name] = nil
end end
@ -241,10 +293,10 @@ end
local search_filters = {} local search_filters = {}
function craftguide.add_search_filter(name, f) function craftguide.add_search_filter(name, f)
if not is_str(name) or name == "" then if not is_str(name) then
return log("error", "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 log("error", "craftguide.add_search_filter(): function missing") return err("craftguide.add_search_filter(): function missing")
end end
search_filters[name] = f search_filters[name] = f
@ -297,8 +349,7 @@ local function groups_item_in_recipe(item, recipe)
end end
local function get_filtered_items(player, data) local function get_filtered_items(player, data)
local items, c = {}, 0 local items, known, c = {}, 0, 0
local known = 0
for i = 1, #init_items do for i = 1, #init_items do
local item = init_items[i] local item = init_items[i]
@ -309,10 +360,10 @@ local function get_filtered_items(player, data)
usages = #apply_recipe_filters(usages or {}, player) usages = #apply_recipe_filters(usages or {}, player)
if recipes > 0 or usages > 0 then if recipes > 0 or usages > 0 then
if not data then c = c + 1
c = c + 1 items[c] = item
items[c] = item
else if data then
known = known + recipes + usages known = known + recipes + usages
end end
end end
@ -320,9 +371,9 @@ local function get_filtered_items(player, data)
if data then if data then
data.known_recipes = known data.known_recipes = known
else
return items
end end
return items
end end
local function get_usages(item) local function get_usages(item)
@ -331,7 +382,6 @@ local function get_usages(item)
for _, recipes in pairs(recipes_cache) do for _, recipes in pairs(recipes_cache) do
for i = 1, #recipes do for i = 1, #recipes do
local recipe = recipes[i] local recipe = recipes[i]
if item_in_recipe(item, recipe) then if item_in_recipe(item, recipe) then
c = c + 1 c = c + 1
usages[c] = recipe usages[c] = recipe
@ -348,15 +398,25 @@ local function get_usages(item)
if fuel_cache[item] then if fuel_cache[item] then
usages[#usages + 1] = { usages[#usages + 1] = {
type = "fuel", type = "fuel",
width = 1,
items = {item}, items = {item},
replacements = fuel_cache[item].replacements, replacements = fuel_cache.replacements[item],
} }
end end
return usages return usages
end end
local function get_burntime(item)
return get_craft_result({method = "fuel", items = {item}}).time
end
local function cache_fuel(item)
local burntime = get_burntime(item)
if burntime > 0 then
fuel_cache[item] = burntime
end
end
local function cache_usages(item) local function cache_usages(item)
local usages = get_usages(item) local usages = get_usages(item)
if #usages > 0 then if #usages > 0 then
@ -364,6 +424,13 @@ local function cache_usages(item)
end end
end end
local function cache_recipes(output)
local recipes = get_all_recipes(output) or {}
if #recipes > 0 then
recipes_cache[output] = recipes
end
end
local function get_recipes(item, data, player) local function get_recipes(item, data, player)
local recipes = recipes_cache[item] local recipes = recipes_cache[item]
local usages = usages_cache[item] local usages = usages_cache[item]
@ -444,7 +511,7 @@ local function get_tooltip(item, info)
tooltip = get_desc(reg_items[item]) tooltip = get_desc(reg_items[item])
local function add(str) local function add(str)
return tooltip .. "\n" .. str return fmt("%s\n%s", tooltip, str)
end end
if info.cooktime then if info.cooktime then
@ -494,11 +561,12 @@ local function get_output_fs(fs, L)
local tooltip = custom_recipe and custom_recipe.description or local tooltip = custom_recipe and custom_recipe.description or
L.shapeless and S("Shapeless") or S("Cooking") L.shapeless and S("Shapeless") or S("Cooking")
fs[#fs + 1] = fmt("tooltip[%f,%f;%f,%f;%s]", if CORE_VERSION >= 500 then
pos_x, pos_y, 0.5, 0.5, ESC(tooltip)) fs[#fs + 1] = fmt(FMT.tooltip, pos_x, pos_y, 0.5, 0.5, ESC(tooltip))
end
end end
local arrow_X = L.rightest + (L.s_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,
@ -511,14 +579,14 @@ 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 = clean_name(item) local name = clean_str(item)
local burntime = fuel_cache[name] and fuel_cache[name].burntime
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), output_X, YOFFSET + (sfinv_only and 0.7 or 0),
1.1, 1.1, item, ESC(name), "") 1.1, 1.1, item, ESC(name), "")
local repair = repairable(item) local burntime = fuel_cache[name]
local repair = repairable(name)
if burntime or repair then if burntime or repair then
fs[#fs + 1] = get_tooltip(name, { fs[#fs + 1] = get_tooltip(name, {
@ -541,13 +609,13 @@ end
local function get_recipe_fs(data, fs) local function get_recipe_fs(data, fs)
local recipe = data.recipes[data.rnum] local recipe = data.recipes[data.rnum]
local width = recipe.width local width = recipe.width or 1
local replacements = recipe.replacements local replacements = recipe.replacements
local cooktime, shapeless local cooktime, shapeless
if recipe.type == "cooking" then if recipe.type == "cooking" then
cooktime, width = width, 1 cooktime, width = width, 1
elseif width == 0 then elseif width == 0 and not recipe.custom then
shapeless = true shapeless = true
local n = #recipe.items local n = #recipe.items
width = (n < 5 and n > 1) and 2 or min(3, max(1, n)) width = (n < 5 and n > 1) and 2 or min(3, max(1, n))
@ -612,7 +680,7 @@ local function get_recipe_fs(data, fs)
for j = 1, #replacements do for j = 1, #replacements do
local replacement = replacements[j] local replacement = replacements[j]
if replacement[1] == item then if replacement[1] == item then
label = label .. "\nR" label = "\nR"
replace = replacement[2] replace = replacement[2]
end end
end end
@ -620,16 +688,14 @@ local function get_recipe_fs(data, fs)
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, clean_name(item), ESC(label)) btn_size, btn_size, item, clean_str(item), ESC(label))
local burntime = fuel_cache[item] and fuel_cache[item].burntime
local info = { local info = {
unknown = not reg_items[item],
groups = groups, groups = groups,
burntime = burntime, burntime = fuel_cache[item],
cooktime = cooktime, cooktime = cooktime,
replace = replace, replace = replace,
repair = nil,
} }
for _, v in pairs(info) do for _, v in pairs(info) do
@ -656,17 +722,19 @@ local function make_formspec(name)
local fs = {} local fs = {}
if not sfinv_only then if not sfinv_only then
local bg, middle = match(craftguide.background, "(.-):(%d+)") local bg, middle = match(craftguide.background, "([%w_%.]*)([#%d]*)")
bg = bg or "" bg = bg or ""
middle = middle or "10" middle = tonumber(sub(middle, 2)) or 10
fs[#fs + 1] = fmt([[ fs[#fs + 1] = [[
size[9.5,8.4] size[9.5,8.4]
no_prepend[] no_prepend[]
bgcolor[#00000000;false] bgcolor[#0000]
background[1,1;1,1;%s;true%s] ]]
]],
bg, DEV_CORE and ";" .. middle or "") fs[#fs + 1] = CORE_VERSION >= 510 and
fmt("background9[1,1;1,1;%s;true;%d]", bg, middle) or
fmt("background[1,1;1,1;%s;true]", bg)
end end
fs[#fs + 1] = fmt([[ fs[#fs + 1] = fmt([[
@ -682,16 +750,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]",
sfinv_only and 6.35 or 7.85, 0.06,
clr("yellow", data.pagenum), data.pagemax)
fs[#fs + 1] = fmt([[ fs[#fs + 1] = fmt([[
image_button[%f,-0.05;0.8,0.8;%s;prev;;;false;%s^\[colorize:yellow:255] image_button[%f,-0.05;0.8,0.8;%s;prev;;;false;%s^\[colorize:yellow:255]
label[%f,%f;%s / %u]
image_button[%f,-0.05;0.8,0.8;%s;next;;;false;%s^\[colorize:yellow:255] image_button[%f,-0.05;0.8,0.8;%s;next;;;false;%s^\[colorize:yellow:255]
]], ]],
sfinv_only and 5.45 or 6.83, PNG.prev, PNG.prev, sfinv_only and 5.45 or 6.83, PNG.prev, PNG.prev,
sfinv_only and 7.2 or 8.75, PNG.next, PNG.next) sfinv_only and 6.35 or 7.85, 0.06, clr("yellow", data.pagenum), data.pagemax,
sfinv_only and 7.2 or 8.75, PNG.next, 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")
@ -777,7 +843,7 @@ local function search(data)
local item = data.items_raw[i] local item = data.items_raw[i]
local def = reg_items[item] local def = reg_items[item]
local desc = (def and def.description) and lower(def.description) or "" local desc = (def and def.description) and lower(def.description) or ""
local search_in = item .. " " .. desc local search_in = fmt("%s %s", item, desc)
local to_add local to_add
if search_filter then if search_filter then
@ -808,12 +874,140 @@ local function search(data)
data.items = filtered_list data.items = filtered_list
end end
local old_register_alias = core.register_alias
core.register_alias = function(old, new)
old_register_alias(old, new)
alias_cache[new] = old
end
--[[ As `core.get_craft_recipe` and `core.get_all_craft_recipes` do not
return the replacements and toolrepair, we have to override
`core.register_craft` and do some reverse engineering.
See engine's issues #4901 and #8920. ]]
fuel_cache.replacements = {}
local old_register_craft = core.register_craft
core.register_craft = function(def)
old_register_craft(def)
if def.type == "toolrepair" then
toolrepair = def.additional_wear * -100
end
local output = def.output or is_str(def.recipe)
if not output then return end
output = {clean_str(output)}
local groups
if is_group(output[1]) then
groups = extract_groups(output[1])
output = groups_to_items(groups, true)
end
for i = 1, #output do
local name = output[i]
if def.type ~= "fuel" then
def.items = {}
end
if def.type == "fuel" then
fuel_cache[name] = def.burntime
fuel_cache.replacements[name] = def.replacements
elseif def.type == "cooking" then
def.width = def.cooktime
def.cooktime = nil
def.items[1] = def.recipe
elseif def.type == "shapeless" then
def.width = 0
for j = 1, #def.recipe do
def.items[#def.items + 1] = def.recipe[j]
end
else
def.width = #def.recipe[1]
local c = 0
for j = 1, #def.recipe do
if def.recipe[j] then
for h = 1, def.width do
c = c + 1
local it = def.recipe[j][h]
if it and it ~= "" then
def.items[c] = it
end
end
end
end
end
if def.type ~= "fuel" then
def.recipe = nil
recipes_cache[name] = recipes_cache[name] or {}
insert(recipes_cache[name], 1, def)
end
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 c = 0
for name, def in pairs(reg_items) do
if show_item(def) then
local old_name = alias_cache[name]
if old_name then
local old_recipes = recipes_cache[old_name]
local old_usages = usages_cache[old_name]
if old_recipes then
recipes_cache[name] = old_recipes
end
if old_usages then
usages_cache[name] = old_usages
end
end
if not fuel_cache[name] then
cache_fuel(name)
end
if not recipes_cache[name] then
cache_recipes(name)
end
cache_usages(name)
if recipes_cache[name] or usages_cache[name] then
c = c + 1
init_items[c] = name
end
end
end
sort(init_items)
end
local function init_data(name) local function init_data(name)
local items = CORE_VERSION >= 500 and init_items or
(#init_items == 0 and get_init_items() or init_items)
pdata[name] = { pdata[name] = {
filter = "", filter = "",
pagenum = 1, pagenum = 1,
items = init_items, items = items,
items_raw = init_items, items_raw = items,
} }
end end
@ -827,111 +1021,10 @@ local function reset_data(data)
data.items = data.items_raw data.items = data.items_raw
end end
-- As `core.get_craft_recipe` and `core.get_all_craft_recipes` do not return the replacements, if CORE_VERSION >= 500 then
-- we have to override `core.register_craft` and `core.register_alias` and do some reverse engineering. on_mods_loaded(get_init_items)
-- See engine's issues #4901 and #8920.
local old_register_alias = core.register_alias
local current_alias = {}
core.register_alias = function(old, new)
old_register_alias(old, new)
current_alias = {old, new}
end end
local old_register_craft = core.register_craft
core.register_craft = function(recipe)
old_register_craft(recipe)
if recipe.type == "toolrepair" then
toolrepair = recipe.additional_wear * -100
end
local output = recipe.output or
(is_str(recipe.recipe) and recipe.recipe or "")
if output == "" then return end
output = {clean_name(output)}
local groups
if is_group(output[1]) then
groups = extract_groups(output[1])
output = groups_to_items(groups, true)
end
for i = 1, #output do
local item = output[i]
if item == current_alias[1] then
item = current_alias[2]
end
recipe.items = {}
if recipe.type == "fuel" then
fuel_cache[item] = recipe
elseif recipe.type == "cooking" then
recipe.width = recipe.cooktime
recipe.cooktime = nil
recipe.items[1] = recipe.recipe
elseif recipe.type == "shapeless" then
recipe.width = 0
for j = 1, #recipe.recipe do
recipe.items[#recipe.items + 1] = recipe.recipe[j]
end
else
recipe.width = #recipe.recipe[1]
local c = 1
for j = 1, #recipe.recipe do
if recipe.recipe[j] then
for h = 1, recipe.width do
local it = recipe.recipe[j][h]
if it and it ~= "" then
recipe.items[c] = it
end
c = c + 1
end
end
end
end
if recipe.type ~= "fuel" then
recipe.recipe = nil
recipes_cache[item] = recipes_cache[item] or {}
insert(recipes_cache[item], 1, recipe)
end
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 c = 1
for name, def in pairs(reg_items) do
if show_item(def) then
cache_usages(name)
if recipes_cache[name] or usages_cache[name] then
init_items[c] = name
c = c + 1
end
end
end
sort(init_items)
end
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(name) init_data(name)
@ -1131,6 +1224,7 @@ end
if progressive_mode then if progressive_mode then
local PLAYERS = {} local PLAYERS = {}
local POLL_FREQ = 0.25 local POLL_FREQ = 0.25
local HUD_TIMER_MAX = 1.5
local function table_diff(t1, t2) local function table_diff(t1, t2)
local hash = {} local hash = {}
@ -1245,15 +1339,16 @@ if progressive_mode then
return inv_items return inv_items
end end
local function show_hud_success(player, data, dtime) local function show_hud_success(player, data)
-- It'd better to have an engine function `hud_move` to do not -- It'd better to have an engine function `hud_move` to only need
-- depend on the server dtime, and use the client dtime internally instead. -- 2 calls for the notification's back and forth.
local hud_info_bg = player:hud_get(data.hud.bg) local hud_info_bg = player:hud_get(data.hud.bg)
local dt = 0.016
if hud_info_bg.position.y <= 0.9 then if hud_info_bg.position.y <= 0.9 then
data.show_hud = false data.show_hud = false
data.hud_timer = (data.hud_timer or 0) + dtime data.hud_timer = (data.hud_timer or 0) + dt
end end
if data.show_hud then if data.show_hud then
@ -1262,7 +1357,7 @@ if progressive_mode then
player:hud_change(def, "position", { player:hud_change(def, "position", {
x = hud_info.position.x, x = hud_info.position.x,
y = hud_info.position.y - (dtime / 5) y = hud_info.position.y - (dt / 5)
}) })
end end
@ -1270,13 +1365,13 @@ if progressive_mode then
S("@1 new recipe(s) discovered!", data.discovered)) S("@1 new recipe(s) discovered!", data.discovered))
elseif data.show_hud == false then elseif data.show_hud == false then
if data.hud_timer > 3 then if data.hud_timer >= HUD_TIMER_MAX then
for _, def in pairs(data.hud) do for _, def in pairs(data.hud) do
local hud_info = player:hud_get(def) local hud_info = player:hud_get(def)
player:hud_change(def, "position", { player:hud_change(def, "position", {
x = hud_info.position.x, x = hud_info.position.x,
y = hud_info.position.y + (dtime / 5) y = hud_info.position.y + (dt / 5)
}) })
end end
@ -1303,12 +1398,19 @@ if progressive_mode then
data.inv_items = table_merge(diff, data.inv_items) data.inv_items = table_merge(diff, data.inv_items)
local oldknown = data.known_recipes or 0 local oldknown = data.known_recipes or 0
get_filtered_items(player, data) local items = get_filtered_items(player, data)
data.discovered = data.known_recipes - oldknown data.discovered = data.known_recipes - oldknown
if data.show_hud == nil and data.discovered > 0 then if data.show_hud == nil and data.discovered > 0 then
data.show_hud = true data.show_hud = true
end end
if sfinv_only then
data.items_raw = items
search(data)
sfinv.set_player_inventory_formspec(player)
end
end end
end end
@ -1317,14 +1419,14 @@ if progressive_mode then
poll_new_items() poll_new_items()
globalstep(function(dtime) globalstep(function()
for i = 1, #PLAYERS do for i = 1, #PLAYERS do
local player = PLAYERS[i] local player = PLAYERS[i]
local name = player:get_player_name() local name = player:get_player_name()
local data = pdata[name] local data = pdata[name]
if data.show_hud ~= nil then if data.show_hud ~= nil then
show_hud_success(player, data, dtime) show_hud_success(player, data)
end end
end end
end) end)
@ -1334,12 +1436,17 @@ if progressive_mode then
on_joinplayer(function(player) on_joinplayer(function(player)
PLAYERS = get_players() PLAYERS = get_players()
local meta = player:get_meta()
local name = player:get_player_name() local name = player:get_player_name()
local data = pdata[name] local data = pdata[name]
data.inv_items = deserialize(meta:get_string("inv_items")) or {} if CORE_VERSION >= 500 then
data.known_recipes = deserialize(meta:get_string("known_recipes")) or 0 local meta = player:get_meta()
data.inv_items = dslz(meta:get_string("inv_items")) or {}
data.known_recipes = dslz(meta:get_string("known_recipes")) or 0
else
data.inv_items = dslz(player:get_attribute("inv_items")) or {}
data.known_recipes = dslz(player:get_attribute("known_recipes")) or 0
end
data.hud = { data.hud = {
bg = player:hud_add({ bg = player:hud_add({
@ -1374,13 +1481,22 @@ if progressive_mode then
} }
local function save_meta(player) local function save_meta(player)
local meta = player:get_meta() local meta
local name = player:get_player_name() local name = player:get_player_name()
local data = pdata[name] local data = pdata[name]
if CORE_VERSION >= 500 then
meta = player:get_meta()
end
for i = 1, #to_save do for i = 1, #to_save do
local meta_name = to_save[i] local meta_name = to_save[i]
meta:set_string(meta_name, serialize(data[meta_name]))
if CORE_VERSION >= 500 then
meta:set_string(meta_name, slz(data[meta_name]))
else
player:set_attribute(meta_name, slz(data[meta_name]))
end
end end
end end
@ -1462,8 +1578,8 @@ register_command("craft", {
}) })
function craftguide.show(name, item, show_usages) function craftguide.show(name, item, show_usages)
if not is_str(name) or name == "" then if not is_str(name) then
return log("error", "craftguide.show(): player name missing") return err("craftguide.show(): player name missing")
end end
local data = pdata[name] local data = pdata[name]

23
locale/craftguide.it.tr Normal file
View File

@ -0,0 +1,23 @@
# textdomain: craftguide
Craft Guide=Guida di assemblaggio
Crafting Guide=Guida d'assemblaggio
Crafting Guide Sign=Cartello della guida d'assemblaggio
Usage @1 of @2=Utilizzo @1 di @2
Recipe @1 of @2=Ricetta @1 di @2
Burning time: @1=Tempo di bruciatura: @1
Cooking time: @1=Tempo di cottura: @1
Replaced by @1 on smelting=Sostituito da @1 alla fusione
Replaced by @1 on burning=Sostituito da @1 alla bruciatura
Replaced by @1 on crafting=Sostituito da @1 all'assemblaggio
Repairable by step of @1=Riparabile per passo di @1
Any item belonging to the group(s): @1=Qualunque oggetto appartenente al gruppo: @1
Recipe's too big to be displayed (@1x@2)=La ricetta è troppo grande per essere mostrata (@1x@2)
Shapeless=Senza forma
Cooking=Cottura
No item to show=Nessun oggetto da mostrare
Collect items to reveal more recipes=Raccogli oggetti per svelare più ricette
Show recipe(s) of the pointed node=Mostra la ricetta del nodo puntato
No node pointed=Nessun nodo puntato
You don't know a recipe for this node=Non conosci una ricetta per questo nodo
No recipe for this node=Nessuna ricetta per questo nodo