Compare commits
	
		
			41 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 9433ae2adc | ||
|  | 103624bc28 | ||
|  | bf28a48c40 | ||
|  | bd5c5fcd16 | ||
|  | 095e45197e | ||
|  | 13252049c2 | ||
|  | 87177d0d7f | ||
|  | 109965175d | ||
|  | 4ff200dfd9 | ||
|  | 3baab53b84 | ||
|  | 8a4fbd0933 | ||
|  | 5560374801 | ||
|  | 5e23600001 | ||
|  | f39ca50f3b | ||
|  | 450797e148 | ||
|  | 6d994fc8d5 | ||
|  | 1910b4b345 | ||
|  | 4823a9dd62 | ||
|  | 689840d6f5 | ||
|  | 3f34d275c1 | ||
|  | 8c7408f66f | ||
|  | 4483f60cbc | ||
|  | 79693f5c88 | ||
|  | b8c491a489 | ||
|  | 34231e01df | ||
|  | 2d6951cd0c | ||
|  | df21df2bce | ||
|  | 5669bcdcb7 | ||
|  | 3ad05328bf | ||
|  | 7793019357 | ||
|  | a97c0b96b3 | ||
|  | 63769603c4 | ||
|  | 189a3ff971 | ||
|  | ca723202d6 | ||
|  | a3e7031c04 | ||
|  | 5fc7e7c087 | ||
|  | aa61333ee3 | ||
|  | e2cdfc28b0 | ||
|  | aa9f7d6da3 | ||
|  | d87c64618c | ||
|  | 3455257df5 | 
| @@ -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 | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										533
									
								
								init.lua
									
									
									
									
									
								
							
							
						
						| @@ -10,10 +10,12 @@ local fuel_cache    = {} | ||||
|  | ||||
| local toolrepair | ||||
|  | ||||
| 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 progressive_mode = core.settings:get_bool "craftguide_progressive_mode" | ||||
| local sfinv_only = core.settings:get_bool "craftguide_sfinv_only" and rawget(_G, "sfinv") | ||||
| local autocache = core.settings:get_bool "craftguide_autocache" | ||||
|  | ||||
| local http = core.request_http_api() | ||||
| local storage = core.get_mod_storage() | ||||
|  | ||||
| local reg_items = core.registered_items | ||||
| local reg_tools = core.registered_tools | ||||
| @@ -41,7 +43,7 @@ local get_player_info = core.get_player_information | ||||
| local on_receive_fields = core.register_on_player_receive_fields | ||||
|  | ||||
| local ESC = core.formspec_escape | ||||
| local S = core.get_translator("craftguide") | ||||
| local S = core.get_translator "craftguide" | ||||
|  | ||||
| local ES = function(...) | ||||
| 	return ESC(S(...)) | ||||
| @@ -56,29 +58,33 @@ local fmt, find, gmatch, match, sub, split, upper, lower = | ||||
| 	string.sub, string.split, string.upper, string.lower | ||||
|  | ||||
| local min, max, floor, ceil = math.min, math.max, math.floor, math.ceil | ||||
| local pairs, next, type, tostring, io = pairs, next, type, tostring, io | ||||
| local pairs, next, type, tostring, unpack = pairs, next, type, tostring, unpack | ||||
| local vec_add, vec_mul = vector.add, vector.multiply | ||||
|  | ||||
| local ROWS  = 9 | ||||
| local FORMSPEC_MINIMAL_VERSION = 3 | ||||
|  | ||||
| local ROWS = 9 | ||||
| local LINES = sfinv_only and 5 or 9 | ||||
| local IPP   = ROWS * LINES | ||||
| local WH_LIMIT = 8 | ||||
|  | ||||
| local XOFFSET = sfinv_only and 3.83 or 11.2 | ||||
| local YOFFSET = sfinv_only and 4.9 or 1 | ||||
|  | ||||
| local PNG = { | ||||
| 	bg       = "craftguide_bg.png", | ||||
| 	bg_full  = "craftguide_bg_full.png", | ||||
| 	search   = "craftguide_search_icon.png", | ||||
| 	clear    = "craftguide_clear_icon.png", | ||||
| 	prev     = "craftguide_next_icon.png^\\[transformFX", | ||||
| 	next     = "craftguide_next_icon.png", | ||||
| 	arrow    = "craftguide_arrow.png", | ||||
| 	fire     = "craftguide_fire.png", | ||||
| 	book     = "craftguide_book.png", | ||||
| 	sign     = "craftguide_sign.png", | ||||
| 	selected = "craftguide_selected.png", | ||||
| 	bg        = "craftguide_bg.png", | ||||
| 	bg_full   = "craftguide_bg_full.png", | ||||
| 	search    = "craftguide_search_icon.png", | ||||
| 	clear     = "craftguide_clear_icon.png", | ||||
| 	prev      = "craftguide_next_icon.png^\\[transformFX", | ||||
| 	next      = "craftguide_next_icon.png", | ||||
| 	arrow     = "craftguide_arrow.png", | ||||
| 	fire      = "craftguide_fire.png", | ||||
| 	fire_anim = "craftguide_fire_anim.png", | ||||
| 	book      = "craftguide_book.png", | ||||
| 	sign      = "craftguide_sign.png", | ||||
| 	nothing   = "craftguide_no.png", | ||||
| 	selected  = "craftguide_selected.png", | ||||
| 	furnace_anim = "craftguide_furnace_anim.png", | ||||
|  | ||||
| 	search_hover = "craftguide_search_icon_hover.png", | ||||
| 	clear_hover  = "craftguide_clear_icon_hover.png", | ||||
| @@ -94,10 +100,16 @@ local FMT = { | ||||
| 	tooltip = "tooltip[%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]", | ||||
| 	animated_image = "animated_image[%f,%f;%f,%f;;%s;%u;%u]", | ||||
| 	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]", | ||||
| } | ||||
|  | ||||
| local function get_fs_version(name) | ||||
| 	local info = get_player_info(name) | ||||
| 	return info and info.formspec_version or 1 | ||||
| end | ||||
|  | ||||
| local function mul_elem(elem, n) | ||||
| 	local fstr, elems = "", {} | ||||
|  | ||||
| @@ -112,6 +124,8 @@ end | ||||
| craftguide.group_stereotypes = { | ||||
| 	dye = "dye:white", | ||||
| 	wool = "wool:white", | ||||
| 	wood = "default:wood", | ||||
| 	tree = "default:tree", | ||||
| 	coal = "default:coal_lump", | ||||
| 	vessel = "vessels:glass_bottle", | ||||
| 	flower = "flowers:dandelion_yellow", | ||||
| @@ -119,12 +133,48 @@ craftguide.group_stereotypes = { | ||||
| 	mesecon_conductor_craftable = "mesecons:wire_00000000_off", | ||||
| } | ||||
|  | ||||
| local group_names = { | ||||
| 	coal = S"Any coal", | ||||
| 	wool = S"Any wool", | ||||
| 	wood = S"Any wood planks", | ||||
| 	sand = S"Any sand", | ||||
| 	stick = S"Any stick", | ||||
| 	stone = S"Any kind of stone block", | ||||
| 	tree  = S"Any tree", | ||||
| 	vessel = S"Any vessel", | ||||
|  | ||||
| 	["color_red,flower"] = S"Any red flower", | ||||
| 	["color_blue,flower"] = S"Any blue flower", | ||||
| 	["color_black,flower"] = S"Any black flower", | ||||
| 	["color_white,flower"] = S"Any white flower", | ||||
| 	["color_green,flower"] = S"Any green flower", | ||||
| 	["color_orange,flower"] = S"Any orange flower", | ||||
| 	["color_yellow,flower"] = S"Any yellow flower", | ||||
| 	["color_violet,flower"] = S"Any violet flower", | ||||
|  | ||||
| 	["color_red,dye"] = S"Any red dye", | ||||
| 	["color_blue,dye"] = S"Any blue dye", | ||||
| 	["color_grey,dye"] = S"Any grey dye", | ||||
| 	["color_pink,dye"] = S"Any pink dye", | ||||
| 	["color_cyan,dye"] = S"Any cyan dye", | ||||
| 	["color_black,dye"] = S"Any black dye", | ||||
| 	["color_white,dye"] = S"Any white dye", | ||||
| 	["color_brown,dye"] = S"Any brown dye", | ||||
| 	["color_green,dye"] = S"Any green dye", | ||||
| 	["color_orange,dye"] = S"Any orange dye", | ||||
| 	["color_yellow,dye"] = S"Any yellow dye", | ||||
| 	["color_violet,dye"] = S"Any violet dye", | ||||
| 	["color_magenta,dye"] = S"Any magenta dye", | ||||
| 	["color_dark_grey,dye"] = S"Any dark grey dye", | ||||
| 	["color_dark_green,dye"] = S"Any dark green dye", | ||||
| } | ||||
|  | ||||
| local function err(str) | ||||
| 	return log("error", str) | ||||
| end | ||||
|  | ||||
| local function msg(name, str) | ||||
| 	return chat_send(name, fmt("[craftguide] %s", clr("#f00", str))) | ||||
| 	return chat_send(name, fmt("[craftguide] %s", str)) | ||||
| end | ||||
|  | ||||
| local function is_str(x) | ||||
| @@ -186,6 +236,7 @@ local function table_eq(T1, T2) | ||||
|  | ||||
| 	local function recurse(t1, t2) | ||||
| 		if type(t1) ~= type(t2) then return end | ||||
|  | ||||
| 		if not is_table(t1) then | ||||
| 			return t1 == t2 | ||||
| 		end | ||||
| @@ -266,7 +317,7 @@ local craft_types = {} | ||||
|  | ||||
| function craftguide.register_craft_type(name, def) | ||||
| 	if not true_str(name) then | ||||
| 		return err"craftguide.register_craft_type(): name missing" | ||||
| 		return err "craftguide.register_craft_type(): name missing" | ||||
| 	end | ||||
|  | ||||
| 	if not is_str(def.description) then | ||||
| @@ -285,8 +336,9 @@ function craftguide.register_craft(def) | ||||
|  | ||||
| 	if true_str(def.url) then | ||||
| 		if not http then | ||||
| 			return err"No HTTP support for this mod. " .. | ||||
| 				"Add it to the `secure.http_mods` or `secure.trusted_mods` setting." | ||||
| 			return err(fmt([[craftguide.register_craft(): Unable to reach %s. | ||||
| 				No HTTP support for this mod: add it to the `secure.http_mods` or | ||||
| 				`secure.trusted_mods` setting.]], def.url)) | ||||
| 		end | ||||
|  | ||||
| 		http.fetch({url = def.url}, function(result) | ||||
| @@ -302,7 +354,7 @@ function craftguide.register_craft(def) | ||||
| 	end | ||||
|  | ||||
| 	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 | ||||
|  | ||||
| 	if #def > 1 then | ||||
| @@ -318,7 +370,7 @@ function craftguide.register_craft(def) | ||||
| 	end | ||||
|  | ||||
| 	if not true_str(def.output) then | ||||
| 		return err"craftguide.register_craft(): output missing" | ||||
| 		return err "craftguide.register_craft(): output missing" | ||||
| 	end | ||||
|  | ||||
| 	if not is_table(def.items) then | ||||
| @@ -388,9 +440,9 @@ local recipe_filters = {} | ||||
|  | ||||
| function craftguide.add_recipe_filter(name, f) | ||||
| 	if not true_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 | ||||
| 		return err"craftguide.add_recipe_filter(): function missing" | ||||
| 		return err "craftguide.add_recipe_filter(): function missing" | ||||
| 	end | ||||
|  | ||||
| 	recipe_filters[name] = f | ||||
| @@ -398,9 +450,9 @@ end | ||||
|  | ||||
| function craftguide.set_recipe_filter(name, f) | ||||
| 	if not is_str(name) then | ||||
| 		return err"craftguide.set_recipe_filter(): name missing" | ||||
| 		return err "craftguide.set_recipe_filter(): name missing" | ||||
| 	elseif not is_func(f) then | ||||
| 		return err"craftguide.set_recipe_filter(): function missing" | ||||
| 		return err "craftguide.set_recipe_filter(): function missing" | ||||
| 	end | ||||
|  | ||||
| 	recipe_filters = {[name] = f} | ||||
| @@ -426,9 +478,9 @@ local search_filters = {} | ||||
|  | ||||
| function craftguide.add_search_filter(name, f) | ||||
| 	if not true_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 | ||||
| 		return err"craftguide.add_search_filter(): function missing" | ||||
| 		return err "craftguide.add_search_filter(): function missing" | ||||
| 	end | ||||
|  | ||||
| 	search_filters[name] = f | ||||
| @@ -457,6 +509,7 @@ end | ||||
|  | ||||
| local function item_in_recipe(item, recipe) | ||||
| 	local clean_item = reg_aliases[item] or item | ||||
|  | ||||
| 	for _, recipe_item in pairs(recipe.items) do | ||||
| 		local clean_recipe_item = reg_aliases[recipe_item] or recipe_item | ||||
| 		if clean_recipe_item == clean_item then | ||||
| @@ -594,7 +647,7 @@ local function get_recipes(item, data, player) | ||||
| 	local no_usages = not usages or #usages == 0 | ||||
|  | ||||
| 	return not no_recipes and recipes or nil, | ||||
| 	       not no_usages  and usages or nil | ||||
| 	       not no_usages  and usages  or nil | ||||
| end | ||||
|  | ||||
| local function groups_to_items(groups, get_all) | ||||
| @@ -644,6 +697,10 @@ local function is_fav(data) | ||||
| end | ||||
|  | ||||
| local function get_desc(name) | ||||
| 	if sub(name, 1, 1) == "_" then | ||||
| 		name = sub(name, 2) | ||||
| 	end | ||||
|  | ||||
| 	local def = reg_items[name] | ||||
|  | ||||
| 	return def and (match(def.description, "%)([%w%s]*)") or def.description) or | ||||
| @@ -655,15 +712,20 @@ local function get_tooltip(name, info) | ||||
| 	local tooltip | ||||
|  | ||||
| 	if info.groups then | ||||
| 		local groupstr, c = {}, 0 | ||||
| 		sort(info.groups) | ||||
| 		tooltip = group_names[concat(info.groups, ",")] | ||||
|  | ||||
| 		for i = 1, #info.groups do | ||||
| 			c = c + 1 | ||||
| 			groupstr[c] = clr("#ff0", info.groups[i]) | ||||
| 		if not tooltip then | ||||
| 			local groupstr, c = {}, 0 | ||||
|  | ||||
| 			for i = 1, #info.groups do | ||||
| 				c = c + 1 | ||||
| 				groupstr[c] = clr("#ff0", info.groups[i]) | ||||
| 			end | ||||
|  | ||||
| 			groupstr = concat(groupstr, ", ") | ||||
| 			tooltip = S("Any item belonging to the group(s): @1", groupstr) | ||||
| 		end | ||||
|  | ||||
| 		groupstr = concat(groupstr, ", ") | ||||
| 		tooltip = S("Any item belonging to the group(s): @1", groupstr) | ||||
| 	else | ||||
| 		tooltip = get_desc(name) | ||||
| 	end | ||||
| @@ -716,41 +778,40 @@ local function get_output_fs(data, fs, L) | ||||
| 		end | ||||
|  | ||||
| 		local pos_x = L.rightest + L.btn_size + 0.1 | ||||
| 		local pos_y = YOFFSET + (sfinv_only and 0.25 or -0.45) | ||||
| 		local pos_y = YOFFSET + (sfinv_only and 0.25 or -0.45) + L.spacing | ||||
|  | ||||
| 		fs[#fs + 1] = fmt(FMT.image, pos_x, pos_y + L.spacing, 0.5, 0.5, icon) | ||||
| 		if sub(icon, 1, 18) == "craftguide_furnace" then | ||||
| 			fs[#fs + 1] = fmt(FMT.animated_image, | ||||
| 				pos_x, pos_y, 0.5, 0.5, PNG.furnace_anim, 8, 180) | ||||
| 		else | ||||
| 			fs[#fs + 1] = fmt(FMT.image, pos_x, pos_y, 0.5, 0.5, icon) | ||||
| 		end | ||||
|  | ||||
| 		local tooltip = custom_recipe and custom_recipe.description or | ||||
| 				L.shapeless and S"Shapeless" or S"Cooking" | ||||
|  | ||||
| 		fs[#fs + 1] = fmt(FMT.tooltip, pos_x, pos_y + L.spacing, 0.5, 0.5, ESC(tooltip)) | ||||
| 		fs[#fs + 1] = fmt(FMT.tooltip, pos_x, pos_y, 0.5, 0.5, ESC(tooltip)) | ||||
| 	end | ||||
|  | ||||
| 	local arrow_X = L.rightest + (L._btn_size or 1.1) | ||||
| 	local output_X = arrow_X + 0.9 | ||||
| 	local Y = YOFFSET + (sfinv_only and 0.7 or 0) + L.spacing | ||||
|  | ||||
| 	fs[#fs + 1] = fmt(FMT.image, | ||||
| 		arrow_X, YOFFSET + (sfinv_only and 0.9 or 0.2) + L.spacing, | ||||
| 		0.9, 0.7, PNG.arrow) | ||||
| 	fs[#fs + 1] = fmt(FMT.image, arrow_X, Y + 0.2, 0.9, 0.7, PNG.arrow) | ||||
|  | ||||
| 	if L.recipe.type == "fuel" then | ||||
| 		fs[#fs + 1] = fmt(FMT.image, | ||||
| 			output_X, YOFFSET + (sfinv_only and 0.7 or 0) + L.spacing, | ||||
| 			1.1, 1.1, PNG.fire) | ||||
| 		fs[#fs + 1] = fmt(FMT.animated_image, output_X, Y, 1.1, 1.1, PNG.fire_anim, 8, 180) | ||||
| 	else | ||||
| 		local item = L.recipe.output | ||||
| 		item = clean_name(item) | ||||
| 		local name = match(item, "%S*") | ||||
|  | ||||
| 		if data.fs_version >= 3 then | ||||
| 			fs[#fs + 1] = fmt(FMT.image, | ||||
| 				output_X, YOFFSET + (sfinv_only and 0.7 or 0) + L.spacing, | ||||
| 				1.1, 1.1, PNG.selected) | ||||
| 		end | ||||
| 		fs[#fs + 1] = fmt(FMT.image, output_X, Y, 1.1, 1.1, PNG.selected) | ||||
|  | ||||
| 		fs[#fs + 1] = fmt(FMT.item_image_button, | ||||
| 			output_X, YOFFSET + (sfinv_only and 0.7 or 0) + L.spacing, | ||||
| 			1.1, 1.1, item, name, "") | ||||
| 		local _name = sfinv_only and name or fmt("_%s", name) | ||||
|  | ||||
| 		fs[#fs + 1] = fmt("item_image_button[%f,%f;%f,%f;%s;%s;%s]", | ||||
| 			output_X, Y, 1.1, 1.1, item, _name, "") | ||||
|  | ||||
| 		local infos = { | ||||
| 			unknown  = not reg_items[name] or nil, | ||||
| @@ -760,7 +821,7 @@ local function get_output_fs(data, fs, L) | ||||
| 		} | ||||
|  | ||||
| 		if next(infos) then | ||||
| 			fs[#fs + 1] = get_tooltip(name, infos) | ||||
| 			fs[#fs + 1] = get_tooltip(_name, infos) | ||||
| 		end | ||||
|  | ||||
| 		if infos.burntime then | ||||
| @@ -768,9 +829,9 @@ local function get_output_fs(data, fs, L) | ||||
| 				output_X + 1, YOFFSET + (sfinv_only and 0.7 or 0.1) + L.spacing, | ||||
| 				0.6, 0.4, PNG.arrow) | ||||
|  | ||||
| 			fs[#fs + 1] = fmt(FMT.image, | ||||
| 			fs[#fs + 1] = fmt(FMT.animated_image, | ||||
| 				output_X + 1.6, YOFFSET + (sfinv_only and 0.55 or 0) + L.spacing, | ||||
| 				0.6, 0.6, PNG.fire) | ||||
| 				0.6, 0.6, PNG.fire_anim, 8, 180) | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
| @@ -825,9 +886,9 @@ local function get_grid_fs(data, fs, rcp, spacing) | ||||
| 			_btn_size = btn_size | ||||
|  | ||||
| 			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)) * (0.83 - (x_y / 5)) | ||||
| 			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 3.92) + x_y) * (0.86 - (x_y / 5)) | ||||
| 		end | ||||
|  | ||||
| 		if X > rightest then | ||||
| @@ -854,14 +915,14 @@ local function get_grid_fs(data, fs, rcp, spacing) | ||||
| 			end | ||||
| 		end | ||||
|  | ||||
| 		if data.fs_version >= 3 and not large_recipe then | ||||
| 			fs[#fs + 1] = fmt(FMT.image, | ||||
| 				X, Y + (sfinv_only and 0.7 or 0), btn_size, btn_size, PNG.selected) | ||||
| 		Y = Y + (sfinv_only and 0.7 or 0) | ||||
|  | ||||
| 		if not large_recipe then | ||||
| 			fs[#fs + 1] = fmt(FMT.image, X, Y, btn_size, btn_size, PNG.selected) | ||||
| 		end | ||||
|  | ||||
| 		fs[#fs + 1] = fmt(FMT.item_image_button, | ||||
| 			X, Y + (sfinv_only and 0.7 or 0), | ||||
| 			btn_size, btn_size, item, item, ESC(label)) | ||||
| 			X, Y, btn_size, btn_size, item, item, label) | ||||
|  | ||||
| 		local infos = { | ||||
| 			unknown  = not reg_items[name] or nil, | ||||
| @@ -892,19 +953,17 @@ local function get_grid_fs(data, fs, rcp, spacing) | ||||
| end | ||||
|  | ||||
| local function get_panels(data, fs) | ||||
| 	local start_y = data.fs_version >= 3 and (sfinv_only and 0.33 or 0) or 0.33 | ||||
| 	local start_y = sfinv_only and 0.33 or 0 | ||||
|  | ||||
| 	local panels = { | ||||
| 		{dat = data.usages or {}, height = 3.5}, | ||||
| 		{dat = data.recipes or {}, height = 3.5}, | ||||
| 	} | ||||
|  | ||||
| 	if data.fs_version >= 3 and not sfinv_only then | ||||
| 		panels.favs = {dat = {}, height = 2.19} | ||||
|  | ||||
| 	elseif sfinv_only then | ||||
| 		panels = data.show_usages and | ||||
| 			{{dat = data.usages}} or {{dat = data.recipes}} | ||||
| 	if not sfinv_only then | ||||
| 		panels.favs = {height = 2.19} | ||||
| 	else | ||||
| 		panels = data.show_usages and {{dat = data.usages}} or {{dat = data.recipes}} | ||||
| 	end | ||||
|  | ||||
| 	for k, v in pairs(panels) do | ||||
| @@ -915,7 +974,7 @@ local function get_panels(data, fs) | ||||
| 			fs[#fs + 1] = fmt("background9[8.1,%f;6.6,%f;%s;false;%d]", | ||||
| 				-0.2 + spacing, v.height, PNG.bg_full, 10) | ||||
|  | ||||
| 			if data.fs_version >= 3 and k == 2 then | ||||
| 			if k == 2 then | ||||
| 				local fav = is_fav(data) | ||||
| 				local nfavs = #data.favs | ||||
|  | ||||
| @@ -935,18 +994,24 @@ local function get_panels(data, fs) | ||||
| 			end | ||||
| 		end | ||||
|  | ||||
| 		local rn = #v.dat | ||||
| 		local rn = v.dat and #v.dat or -1 | ||||
| 		local _rn = tostring(rn) | ||||
| 		local xu = tostring(data.unum) .. _rn | ||||
| 		local xr = tostring(data.rnum) .. _rn | ||||
| 		xu = max(-0.3, -((#xu - 3) * 0.05)) | ||||
| 		xr = max(-0.3, -((#xr - 3) * 0.05)) | ||||
|  | ||||
| 		local is_recipe = k == 2 | ||||
| 		local lbl | ||||
| 		local is_recipe = sfinv_only and not data.show_usages or k == 2 | ||||
| 		local lbl = "" | ||||
|  | ||||
| 		if not sfinv_only and rn == 0 then | ||||
| 			lbl = clr("#f00", is_recipe and ES"No recipes" or ES"No usages") | ||||
| 			local X = XOFFSET - 0.7 | ||||
| 			local Y = YOFFSET - 0.4 + spacing | ||||
|  | ||||
| 			fs[#fs + 1] = fmt(FMT.image, X, Y, 2, 2, PNG.nothing) | ||||
|  | ||||
| 			fs[#fs + 1] = fmt(FMT.tooltip, | ||||
| 				X, Y, 2, 2, is_recipe and ES"No recipes" or ES"No usages") | ||||
|  | ||||
| 		elseif (not sfinv_only and is_recipe) or | ||||
| 				(sfinv_only and not data.show_usages) then | ||||
| @@ -972,45 +1037,37 @@ local function get_panels(data, fs) | ||||
| 			local x_arrow = XOFFSET + (sfinv_only and 1.7 or 1) | ||||
| 			local y_arrow = YOFFSET + (sfinv_only and 3.3 or 1.4 + spacing) | ||||
|  | ||||
| 			if data.fs_version >= 3 then | ||||
| 				fs[#fs + 1] = fmt(mul_elem(FMT.arrow, 2), | ||||
| 					x_arrow + (is_recipe and xr or xu), y_arrow, | ||||
| 						PNG.prev, prev_name, "", | ||||
| 					x_arrow + 1.8, y_arrow, PNG.next, next_name, "") | ||||
| 			else | ||||
| 				fs[#fs + 1] = fmt(mul_elem(FMT.arrow, 2), | ||||
| 					x_arrow + (is_recipe and xr or xu), | ||||
| 						y_arrow, PNG.prev, prev_name, PNG.prev_hover, | ||||
| 					x_arrow + 1.8, y_arrow, PNG.next, next_name, PNG.next_hover) | ||||
| 			end | ||||
| 			fs[#fs + 1] = fmt(mul_elem(FMT.arrow, 2), | ||||
| 				x_arrow + (is_recipe and xr or xu), y_arrow, | ||||
| 					PNG.prev, prev_name, "", | ||||
| 				x_arrow + 1.8, y_arrow, PNG.next, next_name, "") | ||||
| 		end | ||||
|  | ||||
| 		local rcp = is_recipe and v.dat[data.rnum] or v.dat[data.unum] | ||||
| 		local rcp = v.dat and (is_recipe and v.dat[data.rnum] or v.dat[data.unum]) | ||||
| 		if rcp then | ||||
| 			get_grid_fs(data, fs, rcp, spacing) | ||||
| 		end | ||||
|  | ||||
| 		if k == "favs" and data.fs_version >= 3 and not sfinv_only then | ||||
| 		if k == "favs" and not sfinv_only then | ||||
| 			fs[#fs + 1] = fmt(FMT.label, 8.3, spacing - 0.1, ES"Bookmarks") | ||||
|  | ||||
| 			for i = 1, #data.favs do | ||||
| 				local item = data.favs[i] | ||||
| 				local X = 7.85 + (i - 0.5) | ||||
| 				local Y = spacing + 0.45 | ||||
|  | ||||
| 				if data.query_item == item then | ||||
| 					fs[#fs + 1] = fmt(FMT.image, | ||||
| 						7.85 + (i - 0.5), spacing + 0.45, | ||||
| 						1.1, 1.1, PNG.selected) | ||||
| 					fs[#fs + 1] = fmt(FMT.image, X, Y, 1.1, 1.1, PNG.selected) | ||||
| 				end | ||||
|  | ||||
| 				fs[#fs + 1] = fmt(FMT.item_image_button, | ||||
| 					7.85 + (i - 0.5), spacing + 0.45, | ||||
| 					1.1, 1.1, item, item, "") | ||||
| 					X, Y, 1.1, 1.1, item, item, "") | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local function make_formspec(data) | ||||
| local function make_fs(data) | ||||
| 	local fs = {} | ||||
|  | ||||
| 	fs[#fs + 1] = fmt([[ | ||||
| @@ -1018,94 +1075,71 @@ local function make_formspec(data) | ||||
| 		no_prepend[] | ||||
| 		bgcolor[#0000] | ||||
| 	]], | ||||
| 	ROWS + (data.query_item and 6.7 or 0) - 1.2, LINES - 0.3) | ||||
| 	9 + (data.query_item and 6.7 or 0) - 1.2, LINES - 0.3) | ||||
|  | ||||
| 	if not sfinv_only then | ||||
| 		fs[#fs + 1] = fmt("background9[-0.15,-0.2;%f,%f;%s;false;%d]", | ||||
| 			ROWS - 0.9, LINES + 0.4, PNG.bg_full, 10) | ||||
| 			9 - 0.9, LINES + 0.4, PNG.bg_full, 10) | ||||
| 	end | ||||
|  | ||||
| 	fs[#fs + 1] = fmt([[ | ||||
| 		field[0.25,0.2;%f,1;filter;;%s] | ||||
| 		style[filter;border=false] | ||||
| 		field[0.4,0.2;6.45,1;filter;;%s] | ||||
| 		field_close_on_enter[filter;false] | ||||
| 		box[0,0;6.35,0.6;#bababa25] | ||||
| 	]], | ||||
| 	sfinv_only and 2.76 or 2.72, ESC(data.filter)) | ||||
| 	ESC(data.filter)) | ||||
|  | ||||
| 	if data.fs_version >= 3 then | ||||
| 		fs[#fs + 1] = fmt([[ | ||||
| 			style_type[image_button;border=false] | ||||
| 			style_type[item_image_button;border=false;bgimg_hovered=%s;bgimg_pressed=%s] | ||||
| 			style[search;fgimg=%s;fgimg_hovered=%s] | ||||
| 			style[clear;fgimg=%s;fgimg_hovered=%s] | ||||
| 			style[prev_page;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s] | ||||
| 			style[next_page;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s] | ||||
| 		]], | ||||
| 		PNG.selected, PNG.selected, | ||||
| 		PNG.search, PNG.search_hover, | ||||
| 		PNG.clear, PNG.clear_hover, | ||||
| 		PNG.prev, PNG.prev_hover, PNG.prev_hover, | ||||
| 		PNG.next, PNG.next_hover, PNG.next_hover) | ||||
| 	fs[#fs + 1] = fmt([[ | ||||
| 		style_type[image;noclip=false] | ||||
| 		style_type[image_button;border=false] | ||||
| 		style_type[item_image_button;border=false;bgimg_hovered=%s;bgimg_pressed=%s] | ||||
| 		style[search;fgimg=%s;fgimg_hovered=%s] | ||||
| 		style[clear;fgimg=%s;fgimg_hovered=%s] | ||||
| 	]], | ||||
| 	PNG.selected, PNG.selected, | ||||
| 	PNG.search, PNG.search_hover, | ||||
| 	PNG.clear, PNG.clear_hover) | ||||
|  | ||||
| 		fs[#fs + 1] = fmt(mul_elem(FMT.image_button, 4), | ||||
| 			sfinv_only and 2.6 or 2.54, -0.06, 0.85, 0.85, "", "search", "", | ||||
| 			sfinv_only and 3.3 or 3.25, -0.06, 0.85, 0.85, "", "clear", "", | ||||
| 			sfinv_only and 5.45 or (ROWS * 6.83) / 11, -0.06, 0.85, 0.85, "", "prev_page", "", | ||||
| 			sfinv_only and 7.2  or (ROWS * 8.75) / 11, -0.06, 0.85, 0.85, "", "next_page", "") | ||||
| 	else | ||||
| 		fs[#fs + 1] = fmt([[ | ||||
| 			image_button[%f,-0.06;0.85,0.85;%s;search;;;false;%s] | ||||
| 			image_button[%f,-0.06;0.85,0.85;%s;clear;;;false;%s] | ||||
| 			]], | ||||
| 			sfinv_only and 2.6 or 2.54, PNG.search, PNG.search_hover, | ||||
| 			sfinv_only and 3.3 or 3.25, PNG.clear, PNG.clear_hover) | ||||
|  | ||||
| 		fs[#fs + 1] = fmt(mul_elem(FMT.arrow, 2), | ||||
| 			sfinv_only and 5.45 or (ROWS * 6.83) / 11, -0.05, | ||||
| 				PNG.prev, "prev_page", PNG.prev_hover, | ||||
| 			sfinv_only and 7.2 or (ROWS * 8.75) / 11, -0.05, | ||||
| 				PNG.next, "next_page", PNG.next_hover) | ||||
| 	end | ||||
|  | ||||
| 	data.pagemax = max(1, ceil(#data.items / IPP)) | ||||
|  | ||||
| 	fs[#fs + 1] = fmt("label[%f,%f;%s / %u]", | ||||
| 		sfinv_only and 6.35 or (ROWS * 7.85) / 11, | ||||
| 			0.06, clr("#ff0", data.pagenum), data.pagemax) | ||||
| 	fs[#fs + 1] = fmt(mul_elem(FMT.image_button, 2), | ||||
| 		sfinv_only and 2.6 or 6.45, -0.06, 0.85, 0.85, "", "search", "", | ||||
| 		sfinv_only and 3.3 or 7.15, -0.06, 0.85, 0.85, "", "clear", "") | ||||
|  | ||||
| 	if #data.items == 0 then | ||||
| 		local no_item = S"No item to show" | ||||
| 		local pos = ROWS / 3 | ||||
| 		local no_item = ES"No item to show" | ||||
| 		local pos = 3 | ||||
|  | ||||
| 		if next(recipe_filters) and #init_items > 0 and data.filter == "" then | ||||
| 			no_item = S"Collect items to reveal more recipes" | ||||
| 			no_item = ES"Collect items to reveal more recipes" | ||||
| 			pos = pos - 1 | ||||
| 		end | ||||
|  | ||||
| 		fs[#fs + 1] = fmt(FMT.label, pos, 2, ESC(no_item)) | ||||
| 		fs[#fs + 1] = fmt(FMT.label, pos, 2, no_item) | ||||
| 	end | ||||
|  | ||||
| 	local first_item = (data.pagenum - 1) * IPP | ||||
| 	fs[#fs + 1] = "scroll_container[0,1.3;9,9.3;scrbar;vertical]" | ||||
|  | ||||
| 	for i = first_item, first_item + IPP - 1 do | ||||
| 	for i = 0, #data.items do | ||||
| 		local item = data.items[i + 1] | ||||
| 		if not item then break end | ||||
|  | ||||
| 		local X = i % ROWS | ||||
| 		local Y = (i % IPP - X) / ROWS + 1 | ||||
| 		local Y = (i - X) / ROWS | ||||
| 		X = X - (X * 0.12) | ||||
| 		Y = Y - (Y * 0.02) | ||||
|  | ||||
| 		if data.fs_version >= 3 and data.query_item == item then | ||||
| 			fs[#fs + 1] = fmt(FMT.image, | ||||
| 				X - (X * (sfinv_only and 0.12 or 0.14)) - 0.05, | ||||
| 				Y - (Y * 0.1) - 0.1, | ||||
| 				1, 1, PNG.selected) | ||||
| 		if data.query_item == item then | ||||
| 			fs[#fs + 1] = fmt(FMT.image, X, Y, 1, 1, PNG.selected) | ||||
| 		end | ||||
|  | ||||
| 		fs[#fs + 1] = fmt("item_image_button[%f,%f;%f,%f;%s;%s_inv;]", | ||||
| 			X - (X * (sfinv_only and 0.12 or 0.14)) - 0.05, | ||||
| 			Y - (Y * 0.1) - 0.1, | ||||
| 			1, 1, item, item) | ||||
| 			X, Y, 1, 1, item, item) | ||||
| 	end | ||||
|  | ||||
| 	fs[#fs + 1] = "scroll_container_end[]" | ||||
| 	fs[#fs + 1] = fmt("scrollbaroptions[arrows=hide;max=%u]", (#data.items / 8) * 10 - 80) | ||||
| 	fs[#fs + 1] = fmt("scrollbar[7.2,0.8;0.45,8.1;vertical;scrbar;%u]", data.scrbar) | ||||
|  | ||||
| 	if (data.recipes and #data.recipes > 0) or (data.usages and #data.usages > 0) then | ||||
| 		get_panels(data, fs) | ||||
| 	end | ||||
| @@ -1118,7 +1152,7 @@ local show_fs = function(player, name) | ||||
| 	if sfinv_only then | ||||
| 		sfinv.set_player_inventory_formspec(player) | ||||
| 	else | ||||
| 		show_formspec(name, "craftguide", make_formspec(data)) | ||||
| 		show_formspec(name, "craftguide", make_fs(data)) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| @@ -1132,16 +1166,6 @@ craftguide.register_craft_type("digging_chance", { | ||||
| 	icon = "default_tool_mesepick.png", | ||||
| }) | ||||
|  | ||||
| local function sfind(str, filter) | ||||
| 	if filter == "" then | ||||
| 		return 0 | ||||
| 	end | ||||
|  | ||||
| 	if find(str, filter, 1, true) then | ||||
| 		return #str - #filter | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local function search(data) | ||||
| 	local filter = data.filter | ||||
|  | ||||
| @@ -1163,28 +1187,30 @@ local function search(data) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	local filtered_list, order, c = {}, {}, 0 | ||||
| 	local filtered_list, c = {}, 0 | ||||
|  | ||||
| 	for i = 1, #data.items_raw do | ||||
| 		local item = data.items_raw[i] | ||||
| 		local def  = reg_items[item] | ||||
| 		local desc = (def and def.description) and lower(def.description) or "" | ||||
| 		local search_in = fmt("%s %s", item, desc) | ||||
| 		local to_add | ||||
|  | ||||
| 		if search_filter then | ||||
| 			for filter_name, values in pairs(filters) do | ||||
| 				local func = search_filters[filter_name] | ||||
| 				to_add = func(item, values) and (search_filter == "" or | ||||
| 					(sfind(item, search_filter) or sfind(desc, search_filter))) | ||||
| 				if values then | ||||
| 					local func = search_filters[filter_name] | ||||
| 					to_add = func(item, values) and (search_filter == "" or | ||||
| 						find(search_in, search_filter, 1, true)) | ||||
| 				end | ||||
| 			end | ||||
| 		else | ||||
| 			to_add = sfind(item, filter) or sfind(desc, filter) | ||||
| 			to_add = find(search_in, filter, 1, true) | ||||
| 		end | ||||
|  | ||||
| 		if to_add then | ||||
| 			c = c + 1 | ||||
| 			filtered_list[c] = item | ||||
| 			order[item] = to_add | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| @@ -1197,10 +1223,6 @@ local function search(data) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	sort(filtered_list, function(a, b) | ||||
| 		return order[a] < order[b] | ||||
| 	end) | ||||
|  | ||||
| 	data.items = filtered_list | ||||
| end | ||||
|  | ||||
| @@ -1378,8 +1400,7 @@ local function handle_drops_table(name, drop) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local function register_drops(name, def) | ||||
| 	local drop = def.drop | ||||
| local function register_drops(name, drop) | ||||
| 	local dstack = ItemStack(drop) | ||||
|  | ||||
| 	if not dstack:is_empty() and dstack:get_name() ~= name then | ||||
| @@ -1437,59 +1458,46 @@ local function show_item(def) | ||||
| 		def.description and def.description ~= "" | ||||
| end | ||||
|  | ||||
| local function tablelen(t) | ||||
| 	local c = 0 | ||||
| 	for _ in pairs(t) do | ||||
| 		c = c + 1 | ||||
| 	end | ||||
|  | ||||
| 	return c | ||||
| end | ||||
|  | ||||
| local function get_init_items() | ||||
| 	local ic, it, last_str = 0, tablelen(reg_items), "" | ||||
| 	local hash = {} | ||||
| 	local init_items_bak = storage:get "init_items" | ||||
|  | ||||
| 	local function iop(str) | ||||
| 		io.write(("\b \b"):rep(#last_str)) | ||||
| 		io.write(str) | ||||
| 		io.flush() | ||||
| 		last_str = str | ||||
| 	end | ||||
| 	if autocache == false and init_items_bak then | ||||
| 		init_items    = dslz(init_items_bak) | ||||
| 		fuel_cache    = dslz(storage:get "fuel_cache") | ||||
| 		usages_cache  = dslz(storage:get "usages_cache") | ||||
| 		recipes_cache = dslz(storage:get "recipes_cache") | ||||
| 	else | ||||
| 		print "[craftguide] Caching data (this may take a while)" | ||||
| 		local hash = {} | ||||
|  | ||||
| 	local full_char, empty_char = "▰", "▱" | ||||
| 		for name, def in pairs(reg_items) do | ||||
| 			if show_item(def) then | ||||
| 				if not fuel_cache[name] then | ||||
| 					cache_fuel(name) | ||||
| 				end | ||||
|  | ||||
| 	for name, def in pairs(reg_items) do | ||||
| 		ic = ic + 1 | ||||
| 		local percent, bar, len = (ic * 100) / it, "", 20 | ||||
| 				if not recipes_cache[name] then | ||||
| 					cache_recipes(name) | ||||
| 				end | ||||
|  | ||||
| 		for i = 1, len do | ||||
| 			bar = bar .. (i <= percent / (100 / len) and full_char or empty_char) | ||||
| 		end | ||||
| 				cache_usages(name) | ||||
| 				register_drops(name, def.drop) | ||||
|  | ||||
| 		iop(fmt("[craftguide] Caching data  %s  %u%%\r", bar, percent)) | ||||
|  | ||||
| 		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 name ~= "" and recipes_cache[name] or usages_cache[name] then | ||||
| 				init_items[#init_items + 1] = name | ||||
| 				hash[name] = true | ||||
| 				if name ~= "" and recipes_cache[name] or usages_cache[name] then | ||||
| 					init_items[#init_items + 1] = name | ||||
| 					hash[name] = true | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	handle_aliases(hash) | ||||
| 	sort(init_items) | ||||
| 		handle_aliases(hash) | ||||
| 		sort(init_items) | ||||
|  | ||||
| 		storage:set_string("init_items", slz(init_items)) | ||||
| 		storage:set_string("fuel_cache", slz(fuel_cache)) | ||||
| 		storage:set_string("usages_cache", slz(usages_cache)) | ||||
| 		storage:set_string("recipes_cache", slz(recipes_cache)) | ||||
| 	end | ||||
|  | ||||
| 	if http and true_str(craftguide.export_url) then | ||||
| 		local post_data = { | ||||
| @@ -1503,24 +1511,22 @@ local function get_init_items() | ||||
| 			post_data = write_json(post_data), | ||||
| 		} | ||||
| 	end | ||||
|  | ||||
| 	print() | ||||
| end | ||||
|  | ||||
| local function init_data(name) | ||||
| 	pdata[name] = { | ||||
| 		filter     = "", | ||||
| 		pagenum    = 1, | ||||
| 		scrbar     = 0, | ||||
| 		items      = init_items, | ||||
| 		items_raw  = init_items, | ||||
| 		favs       = {}, | ||||
| 		fs_version = get_player_info(name).formspec_version, | ||||
| 		fs_version = get_fs_version(name), | ||||
| 	} | ||||
| end | ||||
|  | ||||
| local function reset_data(data) | ||||
| 	data.filter      = "" | ||||
| 	data.pagenum     = 1 | ||||
| 	data.scrbar      = 0 | ||||
| 	data.rnum        = 1 | ||||
| 	data.unum        = 1 | ||||
| 	data.query_item  = nil | ||||
| @@ -1543,40 +1549,28 @@ local function fields(player, _f) | ||||
|  | ||||
| 	if _f.clear then | ||||
| 		reset_data(data) | ||||
| 		return true, show_fs(player, name) | ||||
|  | ||||
| 	elseif _f.prev_recipe or _f.next_recipe then | ||||
| 		local num = data.rnum + (_f.prev_recipe and -1 or 1) | ||||
| 		data.rnum = data.recipes[num] and num or (_f.prev_recipe and #data.recipes or 1) | ||||
| 		return true, show_fs(player, name) | ||||
|  | ||||
| 	elseif _f.prev_usage or _f.next_usage then | ||||
| 		local num = data.unum + (_f.prev_usage and -1 or 1) | ||||
| 		data.unum = data.usages[num] and num or (_f.prev_usage and #data.usages or 1) | ||||
| 		return true, show_fs(player, name) | ||||
|  | ||||
| 	elseif (_f.key_enter_field == "filter" or _f.search) and _f.filter ~= "" then | ||||
| 	elseif _f.key_enter_field == "filter" or _f.search then | ||||
| 		if _f.filter == "" then | ||||
| 			reset_data(data) | ||||
| 			return true, show_fs(player, name) | ||||
| 		end | ||||
|  | ||||
| 		local str = lower(_f.filter) | ||||
| 		if data.filter == str then return end | ||||
|  | ||||
| 		data.filter = str | ||||
| 		data.pagenum = 1 | ||||
| 		data.scrbar = 0 | ||||
| 		search(data) | ||||
|  | ||||
| 		return true, show_fs(player, name) | ||||
|  | ||||
| 	elseif _f.prev_page or _f.next_page then | ||||
| 		if data.pagemax == 1 then return end | ||||
| 		data.pagenum = data.pagenum - (_f.prev_page and 1 or -1) | ||||
|  | ||||
| 		if data.pagenum > data.pagemax then | ||||
| 			data.pagenum = 1 | ||||
| 		elseif data.pagenum == 0 then | ||||
| 			data.pagenum = data.pagemax | ||||
| 		end | ||||
|  | ||||
| 		return true, show_fs(player, name) | ||||
|  | ||||
| 	elseif _f.fav then | ||||
| 		local fav, i = is_fav(data) | ||||
| 		local total = #data.favs | ||||
| @@ -1586,8 +1580,6 @@ local function fields(player, _f) | ||||
| 		elseif fav then | ||||
| 			remove(data.favs, i) | ||||
| 		end | ||||
|  | ||||
| 		return true, show_fs(player, name) | ||||
| 	else | ||||
| 		local item | ||||
| 		for field in pairs(_f) do | ||||
| @@ -1601,6 +1593,8 @@ local function fields(player, _f) | ||||
| 			return | ||||
| 		elseif sub(item, -4) == "_inv" then | ||||
| 			item = sub(item, 1, -5) | ||||
| 		elseif sub(item, 1, 1) == "_" then | ||||
| 			item = sub(item, 2) | ||||
| 		end | ||||
|  | ||||
| 		item = reg_aliases[item] or item | ||||
| @@ -1611,6 +1605,8 @@ local function fields(player, _f) | ||||
| 			else | ||||
| 				data.show_usages = not data.show_usages | ||||
| 			end | ||||
| 		elseif item == data.query_item then | ||||
| 			return | ||||
| 		end | ||||
|  | ||||
| 		local recipes, usages = get_recipes(item, data, player) | ||||
| @@ -1622,9 +1618,10 @@ local function fields(player, _f) | ||||
| 		data.usages     = usages | ||||
| 		data.rnum       = 1 | ||||
| 		data.unum       = 1 | ||||
|  | ||||
| 		return true, show_fs(player, name) | ||||
| 		data.scrbar     = tonumber(match(_f.scrbar, "%d+")) | ||||
| 	end | ||||
|  | ||||
| 	return true, show_fs(player, name) | ||||
| end | ||||
|  | ||||
| if sfinv_only then | ||||
| @@ -1633,13 +1630,13 @@ if sfinv_only then | ||||
|  | ||||
| 		is_in_nav = function(self, player, context) | ||||
| 			local name = player:get_player_name() | ||||
| 			return get_player_info(name).formspec_version >= 2 | ||||
| 			return get_fs_version(name) >= FORMSPEC_MINIMAL_VERSION | ||||
| 		end, | ||||
|  | ||||
| 		get = function(self, player, context) | ||||
| 			local name = player:get_player_name() | ||||
| 			local data = pdata[name] | ||||
| 			local formspec = make_formspec(data) | ||||
| 			local formspec = make_fs(data) | ||||
|  | ||||
| 			return sfinv.make_formspec(player, context, formspec) | ||||
| 		end, | ||||
| @@ -1669,9 +1666,18 @@ else | ||||
| 		local name = user:get_player_name() | ||||
| 		local data = pdata[name] | ||||
|  | ||||
| 		if data.fs_version == 1 then | ||||
| 			return msg(name, "Your Minetest client is outdated. " .. | ||||
| 				"Get the latest version on minetest.net to use the Crafting Guide.") | ||||
| 		if data.fs_version < FORMSPEC_MINIMAL_VERSION then | ||||
| 			local fs = fmt([[ | ||||
| 				size[6.6,1.3] | ||||
| 				image[0,0;1,1;%s] | ||||
| 				label[1,0;%s] | ||||
| 				button_exit[2.8,0.8;1,1;;OK] | ||||
| 			]], | ||||
| 			PNG.nothing, | ||||
| 			"Your Minetest client is outdated.\n" .. | ||||
| 			"Get the latest version on minetest.net to use the Crafting Guide.") | ||||
|  | ||||
| 			return show_formspec(name, "craftguide", fs) | ||||
| 		end | ||||
|  | ||||
| 		if next(recipe_filters) then | ||||
| @@ -1679,7 +1685,7 @@ else | ||||
| 			search(data) | ||||
| 		end | ||||
|  | ||||
| 		show_formspec(name, "craftguide", make_formspec(data)) | ||||
| 		show_formspec(name, "craftguide", make_fs(data)) | ||||
| 	end | ||||
|  | ||||
| 	core.register_craftitem("craftguide:book", { | ||||
| @@ -1702,7 +1708,7 @@ else | ||||
| 		paramtype = "light", | ||||
| 		paramtype2 = "wallmounted", | ||||
| 		sunlight_propagates = true, | ||||
| 		groups = {oddly_breakable_by_hand = 1, flammable = 3}, | ||||
| 		groups = {choppy = 1, attached_node = 1, oddly_breakable_by_hand = 1, flammable = 3}, | ||||
| 		node_box = { | ||||
| 			type = "wallmounted", | ||||
| 			wall_top    = {-0.5, 0.4375, -0.5, 0.5, 0.5, 0.5}, | ||||
| @@ -1817,11 +1823,7 @@ if progressive_mode then | ||||
| 		return filtered | ||||
| 	end | ||||
|  | ||||
| 	local item_lists = { | ||||
| 		"main", | ||||
| 		"craft", | ||||
| 		"craftpreview", | ||||
| 	} | ||||
| 	local item_lists = {"main", "craft", "craftpreview"} | ||||
|  | ||||
| 	local function get_inv_items(player) | ||||
| 		local inv = player:get_inventory() | ||||
| @@ -1949,8 +1951,8 @@ if progressive_mode then | ||||
| 		local data = pdata[name] | ||||
|  | ||||
| 		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 | ||||
| 		data.inv_items = dslz(meta:get_string "inv_items") or {} | ||||
| 		data.known_recipes = dslz(meta:get_string "known_recipes") or 0 | ||||
|  | ||||
| 		data.hud = { | ||||
| 			bg = player:hud_add{ | ||||
| @@ -1979,10 +1981,7 @@ if progressive_mode then | ||||
| 		} | ||||
| 	end) | ||||
|  | ||||
| 	local to_save = { | ||||
| 		"inv_items", | ||||
| 		"known_recipes", | ||||
| 	} | ||||
| 	local to_save = {"inv_items", "known_recipes"} | ||||
|  | ||||
| 	local function save_meta(player) | ||||
| 		local meta = player:get_meta() | ||||
| @@ -2015,7 +2014,7 @@ end) | ||||
|  | ||||
| function craftguide.show(name, item, show_usages) | ||||
| 	if not true_str(name)then | ||||
| 		return err"craftguide.show(): player name missing" | ||||
| 		return err "craftguide.show(): player name missing" | ||||
| 	end | ||||
|  | ||||
| 	local data = pdata[name] | ||||
|   | ||||
| @@ -3,17 +3,58 @@ | ||||
| Craft Guide=Rezeptbuch | ||||
| Crafting Guide=Rezeptbuch | ||||
| Crafting Guide Sign=Rezepttafel | ||||
| Bookmarks=Lesezeichen | ||||
| Usage @1 of @2=Verwendung @1 von @2 | ||||
| Recipe @1 of @2=Rezept @1 von @2 | ||||
| No recipes=Keine Rezepte | ||||
| No usages=Keine Verwendungen | ||||
| Burning time: @1=Brennzeit: @1 | ||||
| Cooking time: @1=Kochzeit: @1 | ||||
| Replaced by @1 on smelting=Ersetzt durch @1 beim Schmelzen | ||||
| Replaced by @1 on burning=Ersetzt durch @1 beim Brennen | ||||
| Replaced by @1 on crafting=Ersetzt durch @1 beim Fertigen | ||||
| Repairable by step of @1=Reparierbar um @1 | ||||
| Any item belonging to the group(s): @1=Beliebiger Gegenstand aus Gruppe(n): @1 | ||||
| Any black dye=Beliebiger schwarzer Farbstoff | ||||
| Any black flower=Beliebige schwarze Blume | ||||
| Any blue dye=Beliebiger blauer Farbstoff | ||||
| Any blue flower=Beliebige blaue Blume | ||||
| Any brown dye=Beliebiger brauner Farbstoff | ||||
| Any coal=Beliebige Kohle | ||||
| Any cyan dye=Beliebiger türkiser Farbstoff | ||||
| Any dark green dye=Beliebiger dunkelgrüner Farbstoff | ||||
| Any dark grey dye=Beliebiger dunkelgrauer Farbstoff | ||||
| Any green dye=Beliebiger grüner Farbstoff | ||||
| Any green flower=Beliebige grüne Blume | ||||
| Any grey dye=Beliebiger grauer Farbstoff | ||||
| Any kind of stone block=Beliebiger Steinblock | ||||
| Any magenta dye=Beliebiger magenta Farbstoff | ||||
| Any orange dye=Beliebiger orange Farbstoff | ||||
| Any orange flower=Beliebige orange Blume | ||||
| Any pink dye=Beliebiger rosa Farbstoff | ||||
| Any red dye=Beliebiger roter Farbstoff | ||||
| Any red flower=Beliebige rote Blume | ||||
| Any sand=Beliebiger Sand | ||||
| Any stick=Beliebiger Stock | ||||
| Any tree=Beliebiger Baum | ||||
| Any vessel=Beliebiger Behälter | ||||
| Any violet dye=Beliebiger violetter Farbstoff | ||||
| Any violet flower=Beliebige violette Blume | ||||
| Any white dye=Beliebiger weißer Farbstoff | ||||
| Any white flower=Beliebige weiße Blume | ||||
| Any wood planks=Beliebige Holzplanken | ||||
| Any wool=Beliebige Wolle | ||||
| Any yellow dye=Beliebiger gelber Farbstoff | ||||
| Any yellow flower=Beliebige gelbe Blume | ||||
| Recipe's too big to be displayed (@1x@2)=Rezept ist zu groß für die Anzeige (@1×@2) | ||||
| Shapeless=Formlos | ||||
| Cooking=Kochen | ||||
| No item to show=Nichts anzuzeigen | ||||
| Collect items to reveal more recipes=Gegenstände aufsammeln, um mehr Rezepte aufzudecken | ||||
| Show recipe(s) of the pointed node=Rezept(e) des gezeigten Blocks anzeigen | ||||
| No node pointed=Auf keinen Block gezeigt | ||||
| You don't know a recipe for this node=Sie kennen kein Rezept für diesen Block | ||||
| No recipe for this node=Kein Rezept für diesen Block | ||||
| No node pointed=Auf keinem Block gezeigt | ||||
| You don't know a recipe or usage for this item=Sie kennen kein Rezept und keine Verwendung für diesen Gegenstand | ||||
| No recipe or usage for this item=Kein Rezept und keine Verwendung für diesen Gegenstand | ||||
| Digging=Graben | ||||
| Digging Chance=Grabechance | ||||
| @1 of chance to drop=@1 Abwurfwahrscheinlichkeit | ||||
|   | ||||
| @@ -2,8 +2,12 @@ | ||||
|  | ||||
| Craft Guide=Guide de recettes | ||||
| Crafting Guide=Guide de recettes | ||||
| Crafting Guide Sign=Guide de recettes | ||||
| Bookmarks=Favoris | ||||
| Usage @1 of @2=Usage @1 de @2 | ||||
| Recipe @1 of @2=Recette @1 de @2 | ||||
| No recipes=Pas de recettes | ||||
| No usages=Pas d'usages | ||||
| Burning time: @1=Temps de combustion : @1 | ||||
| Cooking time: @1=Temps de cuisson : @1 | ||||
| Replaced by @1 on smelting=Remplacé par @1 lors de la cuisson | ||||
| @@ -11,6 +15,37 @@ Replaced by @1 on burning=Remplacé par @1 lors de la combustion | ||||
| Replaced by @1 on crafting=Remplacé par @1 lors de la fabrication | ||||
| Repairable by step of @1=Réparable par étape de @1 | ||||
| Any item belonging to the group(s): @1=Tout item appartenant au(x) groupe(s) : @1 | ||||
| Any black dye=Quelconque colorant noir | ||||
| Any black flower=Quelconque fleur noire | ||||
| Any blue dye=Quelconque colorant bleu | ||||
| Any blue flower=Quelconque fleur bleue | ||||
| Any brown dye=Quelconque colorant marron | ||||
| Any coal=Quelconque charbon | ||||
| Any cyan dye=Quelconque colorant bleu ciel | ||||
| Any dark green dye=Quelconque colorant vert foncé | ||||
| Any dark grey dye=Quelconque colorant gris foncé | ||||
| Any green dye=Quelconque colorant vert | ||||
| Any green flower=Quelconque fleur verte | ||||
| Any grey dye=Quelconque colorant gris | ||||
| Any kind of stone block=Quelconque roche | ||||
| Any magenta dye=Quelconque colorant magenta | ||||
| Any orange dye=Quelconque colorant orange | ||||
| Any orange flower=Quelconque fleur orange | ||||
| Any pink dye=Quelconque colorant rose | ||||
| Any red dye=Quelconque colorant rouge | ||||
| Any red flower=Quelconque fleur rouge | ||||
| Any sand=Quelconque sable | ||||
| Any stick=Quelconque bâton | ||||
| Any tree=Quelconque tronc d'arbre | ||||
| Any vessel=Quelconque couvert | ||||
| Any violet dye=Quelconque colorant violet | ||||
| Any violet flower=Quelconque fleur violette | ||||
| Any white dye=Quelconque colorant blanc | ||||
| Any white flower=Quelconque fleur blanche | ||||
| Any wood planks=Quelconques planches de bois | ||||
| Any wool=Quelconque laine | ||||
| Any yellow dye=Quelconque colorant jaune | ||||
| Any yellow flower=Quelconque fleur jaune | ||||
| Recipe's too big to be displayed (@1x@2)=La recette est trop grande pour être affichée (@1x@2) | ||||
| Shapeless=Sans forme | ||||
| Cooking=Cuisson | ||||
| @@ -18,5 +53,8 @@ No item to show=Aucun item à afficher | ||||
| Collect items to reveal more recipes=Collecte des items pour révéler plus de recettes | ||||
| Show recipe(s) of the pointed node=Affiche les recettes du bloc visé | ||||
| No node pointed=Aucun bloc visé | ||||
| You don't know a recipe for this node=Tu ne connais aucune recette pour ce bloc | ||||
| No recipe for this node=Aucune recette pour ce bloc | ||||
| You don't know a recipe or usage for this item=Tu ne connais aucune recette pour ce bloc | ||||
| No recipe or usage for this item=Aucune recette pour ce bloc | ||||
| Digging=Destruction | ||||
| Digging Chance=Destruction chanceuse | ||||
| @1 of chance to drop=@1 de chance de tomber | ||||
|   | ||||
| @@ -2,25 +2,59 @@ | ||||
|  | ||||
| Craft Guide=Guida di assemblaggio | ||||
| Crafting Guide=Guida d'assemblaggio | ||||
| Crafting Guide Sign=Cartello della guida d'assemblaggio | ||||
| Crafting Guide Sign=Cartello della guida di assemblaggio | ||||
| Bookmarks=Segnalibri | ||||
| Usage @1 of @2=Utilizzo @1 di @2 | ||||
| Recipe @1 of @2=Ricetta @1 di @2 | ||||
| Burning time: @1=Tempo di bruciatura: @1 | ||||
| No recipes=Nessuna ricetta | ||||
| No usages=Nessun utilizzo | ||||
| Burning time: @1=Tempo di combustione: @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 burning=Sostituito da @1 alla combustione | ||||
| 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 | ||||
| Any item belonging to the group(s): @1=Qualunque oggetto appartenente al/ai gruppo/i: @1 | ||||
| Any black dye=Qualunque tintura nera | ||||
| Any black flower=Qualunque fiore nero | ||||
| Any blue dye=Qualunque tintura blu | ||||
| Any blue flower=Qualunque fiore blu | ||||
| Any brown dye=Qualunque tintura marrone | ||||
| Any coal=Qualunque carbone | ||||
| Any cyan dye=Qualunque tintura ciano | ||||
| Any dark green dye=Qualunque tintura verde scura | ||||
| Any dark grey dye=Qualunque tintura grigio scura | ||||
| Any green dye=Qualunque tintura verde | ||||
| Any green flower=Qualunque fiore verde | ||||
| Any grey dye=Qualunque tintura grigia | ||||
| Any kind of stone block=Qualunque tipo di blocco di pietra | ||||
| Any magenta dye=Qualunque tintura magenta | ||||
| Any orange dye=Qualunque tintura arancione | ||||
| Any orange flower=Qualunque fiore arancione | ||||
| Any pink dye=Qualunque tintura rosa | ||||
| Any red dye=Qualunque tintura rossa | ||||
| Any red flower=Qualunque fiore rosso | ||||
| Any sand=Qualunque sabbia | ||||
| Any stick=Qualunque bastone | ||||
| Any tree=Qualunque albero | ||||
| Any vessel=Qualunque contenitore | ||||
| Any violet dye=Qualunque tintura viola | ||||
| Any violet flower=Qualunque fiore viola | ||||
| Any white dye=Qualunque tintura bianca | ||||
| Any white flower=Qualunque fiore bianco | ||||
| Any wood planks=Qualunque asse di legno | ||||
| Any wool=Qualunque lana | ||||
| Any yellow dye=Qualunque tintura gialla | ||||
| Any yellow flower=Qualunque fiore giallo | ||||
| 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 | ||||
| Show recipe(s) of the pointed node=Mostra la/le ricetta/e 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 | ||||
| You don't know a recipe or usage for this item=Non conosci una ricetta o un utilizzo per questo oggetto | ||||
| No recipe or usage for this item=Nessuna ricetta o utilizzo per questo oggetto | ||||
| Digging=Scavando | ||||
| Digging Chance=Probabilità di scavare | ||||
| @1 of chance to drop=@1 di probabilità di rilascio | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| Craft Guide= | ||||
| Crafting Guide= | ||||
| Crafting Guide Sign= | ||||
| Bookmarks= | ||||
| Usage @1 of @2= | ||||
| Recipe @1 of @2= | ||||
| No recipes= | ||||
| @@ -14,6 +15,37 @@ Replaced by @1 on burning= | ||||
| Replaced by @1 on crafting= | ||||
| Repairable by step of @1= | ||||
| Any item belonging to the group(s): @1= | ||||
| Any black dye= | ||||
| Any black flower= | ||||
| Any blue dye= | ||||
| Any blue flower= | ||||
| Any brown dye= | ||||
| Any coal= | ||||
| Any cyan dye= | ||||
| Any dark green dye= | ||||
| Any dark grey dye= | ||||
| Any green dye= | ||||
| Any green flower= | ||||
| Any grey dye= | ||||
| Any kind of stone block= | ||||
| Any magenta dye= | ||||
| Any orange dye= | ||||
| Any orange flower= | ||||
| Any pink dye= | ||||
| Any red dye= | ||||
| Any red flower= | ||||
| Any sand= | ||||
| Any stick= | ||||
| Any tree= | ||||
| Any vessel= | ||||
| Any violet dye= | ||||
| Any violet flower= | ||||
| Any white dye= | ||||
| Any white flower= | ||||
| Any wood planks= | ||||
| Any wool= | ||||
| Any yellow dye= | ||||
| Any yellow flower= | ||||
| Recipe's too big to be displayed (@1x@2)= | ||||
| Shapeless= | ||||
| Cooking= | ||||
|   | ||||
| @@ -1,5 +1,12 @@ | ||||
| # The progressive mode shows recipes you can craft from items you ever had in your inventory. | ||||
| craftguide_progressive_mode	(Progressive Mode)	bool false | ||||
| craftguide_progressive_mode    (Learn crafting recipes progressively)    bool false | ||||
|  | ||||
| # Integration in the default Minetest Game inventory. | ||||
| craftguide_sfinv_only		(Sfinv only)		bool false | ||||
| craftguide_sfinv_only    (Crafting Guide in inventory only)    bool false | ||||
|  | ||||
| # Enable pre-caching of item recipes. | ||||
| # Do NOT disable the first time the mod loads. | ||||
| # Disabling the auto-caching will result in faster mod loading. | ||||
| # If you enable or disable mods, or edit the current mod recipes in your setup, you SHOULD re-enable this setting until the next caching at least. | ||||
| # Usage at your own risk. | ||||
| craftguide_autocache    (Auto-caching of recipes)    bool true | ||||
|   | ||||
| Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 4.8 KiB | 
| Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 1.5 KiB | 
| Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 5.5 KiB | 
| Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 4.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								textures/craftguide_no.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.9 KiB | 
| Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 3.5 KiB |