diff options
Diffstat (limited to 'unified_inventory/register.lua')
| -rw-r--r-- | unified_inventory/register.lua | 261 | 
1 files changed, 129 insertions, 132 deletions
diff --git a/unified_inventory/register.lua b/unified_inventory/register.lua index d065e82..6b4454c 100644 --- a/unified_inventory/register.lua +++ b/unified_inventory/register.lua @@ -266,64 +266,77 @@ unified_inventory.register_page("craftguide", {  		local player_name = player:get_player_name()  		local player_privs = minetest.get_player_privs(player_name) -		local formspec = "" -		formspec = formspec.."background[0,"..(formspecy + 3.5)..";8,4;ui_main_inventory.png]" -		formspec = formspec.."label[0,"..formheadery..";" .. F(S("Crafting Guide")) .. "]" -		formspec = formspec.."listcolors[#00000000;#00000000]" +		local fs = { +			"background[0,"..(formspecy + 3.5)..";8,4;ui_main_inventory.png]", +			"label[0,"..formheadery..";" .. F(S("Crafting Guide")) .. "]", +			"listcolors[#00000000;#00000000]" +		}  		local item_name = unified_inventory.current_item[player_name] -		if not item_name then return {formspec=formspec} end +		if not item_name then +			return { formspec = table.concat(fs) } +		end +  		local item_name_shown -		if minetest.registered_items[item_name] and minetest.registered_items[item_name].description then -			item_name_shown = string.format(S("%s (%s)"), minetest.registered_items[item_name].description, item_name) +		if minetest.registered_items[item_name] +				and minetest.registered_items[item_name].description then +			item_name_shown = string.format(S("%s (%s)"), +				minetest.registered_items[item_name].description, item_name)  		else  			item_name_shown = item_name  		end  		local dir = unified_inventory.current_craft_direction[player_name] -		local rdir -		if dir == "recipe" then rdir = "usage" end -		if dir == "usage" then rdir = "recipe" end +		local rdir = dir == "recipe" and "usage" or "recipe" +  		local crafts = unified_inventory.crafts_for[dir][item_name]  		local alternate = unified_inventory.alternate[player_name]  		local alternates, craft -		if crafts ~= nil and #crafts > 0 then +		if crafts and #crafts > 0 then  			alternates = #crafts  			craft = crafts[alternate]  		end  		local has_give = player_privs.give or unified_inventory.is_creative(player_name) -		formspec = formspec.."background[0.5,"..(formspecy + 0.2)..";8,3;ui_craftguide_form.png]" -		formspec = formspec.."textarea["..craftresultx..","..craftresulty -                           ..";10,1;;"..F(role_text[dir])..": "..item_name_shown..";]" -		formspec = formspec..stack_image_button(0, formspecy, 1.1, 1.1, "item_button_" -		                   .. rdir .. "_", ItemStack(item_name)) +		fs[#fs + 1] = "background[0.5,"..(formspecy + 0.2)..";8,3;ui_craftguide_form.png]" +		fs[#fs + 1] = string.format("textarea[%f,%f;10,1;;%s: %s;]", +				craftresultx, craftresulty, F(role_text[dir]), item_name_shown) +		fs[#fs + 1] = stack_image_button(0, formspecy, 1.1, 1.1, +				"item_button_" .. rdir .. "_", ItemStack(item_name))  		if not craft then -			formspec = formspec.."label[5.5,"..(formspecy + 2.35)..";" -			                   ..F(no_recipe_text[dir]).."]" +			-- No craft recipes available for this item. +			fs[#fs + 1] = "label[5.5,"..(formspecy + 2.35)..";" +					.. F(no_recipe_text[dir]) .. "]"  			local no_pos = dir == "recipe" and 4.5 or 6.5  			local item_pos = dir == "recipe" and 6.5 or 4.5 -			formspec = formspec.."image["..no_pos..","..formspecy..";1.1,1.1;ui_no.png]" -			formspec = formspec..stack_image_button(item_pos, formspecy, 1.1, 1.1, "item_button_" -			                   ..other_dir[dir].."_", ItemStack(item_name)) +			fs[#fs + 1] = "image["..no_pos..","..formspecy..";1.1,1.1;ui_no.png]" +			fs[#fs + 1] = stack_image_button(item_pos, formspecy, 1.1, 1.1, +				"item_button_" .. other_dir[dir] .. "_", ItemStack(item_name))  			if has_give then -				formspec = formspec.."label[0,"..(formspecy + 2.10)..";" .. F(S("Give me:")) .. "]" -						.."button[0,  "..(formspecy + 2.7)..";0.6,0.5;craftguide_giveme_1;1]" -						.."button[0.6,"..(formspecy + 2.7)..";0.7,0.5;craftguide_giveme_10;10]" -						.."button[1.3,"..(formspecy + 2.7)..";0.8,0.5;craftguide_giveme_99;99]" +				fs[#fs + 1] = "label[0," .. (formspecy + 2.10) .. ";" .. F(S("Give me:")) .. "]" +						.. "button[0,  " .. (formspecy + 2.7) .. ";0.6,0.5;craftguide_giveme_1;1]" +						.. "button[0.6," .. (formspecy + 2.7) .. ";0.7,0.5;craftguide_giveme_10;10]" +						.. "button[1.3," .. (formspecy + 2.7) .. ";0.8,0.5;craftguide_giveme_99;99]"  			end -			return {formspec = formspec} +			return { formspec = table.concat(fs) }  		end  		local craft_type = unified_inventory.registered_craft_types[craft.type] or  				unified_inventory.craft_type_defaults(craft.type, {})  		if craft_type.icon then -			formspec = formspec..string.format(" image[%f,%f;%f,%f;%s]",5.7,(formspecy + 0.05),0.5,0.5,craft_type.icon) +			fs[#fs + 1] = string.format("image[%f,%f;%f,%f;%s]", +					5.7, (formspecy + 0.05), 0.5, 0.5, craft_type.icon)  		end -		formspec = formspec.."label[5.5,"..(formspecy + 1)..";" .. F(craft_type.description).."]" -		formspec = formspec..stack_image_button(6.5, formspecy, 1.1, 1.1, "item_button_usage_", ItemStack(craft.output)) -		local display_size = craft_type.dynamic_display_size and craft_type.dynamic_display_size(craft) or { width = craft_type.width, height = craft_type.height } -		local craft_width = craft_type.get_shaped_craft_width and craft_type.get_shaped_craft_width(craft) or display_size.width +		fs[#fs + 1] = "label[5.5,"..(formspecy + 1)..";" .. F(craft_type.description).."]" +		fs[#fs + 1] = stack_image_button(6.5, formspecy, 1.1, 1.1, +				"item_button_usage_", ItemStack(craft.output)) + +		local display_size = craft_type.dynamic_display_size +				and craft_type.dynamic_display_size(craft) +				or { width = craft_type.width, height = craft_type.height } +		local craft_width = craft_type.get_shaped_craft_width +				and craft_type.get_shaped_craft_width(craft) +				or display_size.width  		-- This keeps recipes aligned to the right,  		-- so that they're close to the arrow. @@ -358,47 +371,45 @@ unified_inventory.register_page("craftguide", {  			local xof = (fx-1) * of + of  			local yof = (y-1) * of + 1  			if item then -				formspec = formspec..stack_image_button( +				fs[#fs + 1] = stack_image_button(  						xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h,  						"item_button_recipe_",  						ItemStack(item))  			else  				-- Fake buttons just to make grid -				formspec = formspec.."image_button[" -					..tostring(xoffset - xof)..","..tostring(formspecy - 1 + yof) -					..";"..bsize_w..","..bsize_h..";ui_blank_image.png;;]" +				fs[#fs + 1] = string.format("image_button[%f,%f;%f,%f;ui_blank_image.png;;]", +						xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h)  			end  		end  		end  		else  			-- Error -			formspec = formspec.."label[" -				..tostring(2)..","..tostring(formspecy) -				..";"..F(S("This recipe is too\nlarge to be displayed.")).."]" +			fs[#fs + 1] = string.format("label[2,%f;%s]", +				formspecy, F(S("This recipe is too\nlarge to be displayed.")))  		end  		if craft_type.uses_crafting_grid and display_size.width <= 3 then -			formspec = formspec.."label[0,"..(formspecy + 0.9)..";" .. F(S("To craft grid:")) .. "]" -					.."button[0,  "..(formspecy + 1.5)..";0.6,0.5;craftguide_craft_1;1]" -					.."button[0.6,"..(formspecy + 1.5)..";0.7,0.5;craftguide_craft_10;10]" -					.."button[1.3,"..(formspecy + 1.5)..";0.8,0.5;craftguide_craft_max;" .. F(S("All")) .. "]" +			fs[#fs + 1] = "label[0," .. (formspecy + 0.9) .. ";" .. F(S("To craft grid:")) .. "]" +					.. "button[0,  " .. (formspecy + 1.5) .. ";0.6,0.5;craftguide_craft_1;1]" +					.. "button[0.6," .. (formspecy + 1.5) .. ";0.7,0.5;craftguide_craft_10;10]" +					.. "button[1.3," .. (formspecy + 1.5) .. ";0.8,0.5;craftguide_craft_max;" .. F(S("All")) .. "]"  		end  		if has_give then -			formspec = formspec.."label[0,"..(formspecy + 2.1)..";" .. F(S("Give me:")) .. "]" -					.."button[0,  "..(formspecy + 2.7)..";0.6,0.5;craftguide_giveme_1;1]" -					.."button[0.6,"..(formspecy + 2.7)..";0.7,0.5;craftguide_giveme_10;10]" -					.."button[1.3,"..(formspecy + 2.7)..";0.8,0.5;craftguide_giveme_99;99]" +			fs[#fs + 1] = "label[0," .. (formspecy + 2.1) .. ";" .. F(S("Give me:")) .. "]" +					.. "button[0,  " .. (formspecy + 2.7) .. ";0.6,0.5;craftguide_giveme_1;1]" +					.. "button[0.6," .. (formspecy + 2.7) .. ";0.7,0.5;craftguide_giveme_10;10]" +					.. "button[1.3," .. (formspecy + 2.7) .. ";0.8,0.5;craftguide_giveme_99;99]"  		end  		if alternates and alternates > 1 then -			formspec = formspec.."label[5.5,"..(formspecy + 1.6)..";" -					..string.format(F(recipe_text[dir]), alternate, alternates).."]" -					.."image_button[5.5,"..(formspecy + 2)..";1,1;ui_left_icon.png;alternate_prev;]" -					.."image_button[6.5,"..(formspecy + 2)..";1,1;ui_right_icon.png;alternate;]" -					.."tooltip[alternate_prev;"..F(prev_alt_text[dir]).."]" -					.."tooltip[alternate;"..F(next_alt_text[dir]).."]" +			fs[#fs + 1] = "label[5.5," .. (formspecy + 1.6) .. ";" +					.. string.format(F(recipe_text[dir]), alternate, alternates) .. "]" +					.. "image_button[5.5," .. (formspecy + 2) .. ";1,1;ui_left_icon.png;alternate_prev;]" +					.. "image_button[6.5," .. (formspecy + 2) .. ";1,1;ui_right_icon.png;alternate;]" +					.. "tooltip[alternate_prev;" .. F(prev_alt_text[dir]) .. "]" +					.. "tooltip[alternate;" .. F(next_alt_text[dir]) .. "]"  		end -		return {formspec = formspec} +		return { formspec = table.concat(fs) }  	end,  }) @@ -429,78 +440,63 @@ local function craftguide_giveme(player, formname, fields)  	player_inv:add_item("main", {name = output, count = amount})  end --- tells if an item can be moved and returns an index if so -local function item_fits(player_inv, craft_item, needed_item) -	local need_group = string.sub(needed_item, 1, 6) == "group:" -	if need_group then -		need_group = string.sub(needed_item, 7) +-- Takes any stack from "main" where the `amount` of `needed_item` may fit +-- into the given crafting stack (`craft_item`) +local function craftguide_move_stacks(inv, craft_item, needed_item, amount) +	if craft_item:get_count() >= amount then +		return  	end -	if craft_item -	and not craft_item:is_empty() then -		local ciname = craft_item:get_name() -		-- abort if the item there isn't usable -		if ciname ~= needed_item -		and not need_group then -			return -		end - -		-- abort if no item fits onto it -		if craft_item:get_count() >= craft_item:get_definition().stack_max then -			return -		end - -		-- use the item there if it's in the right group and a group item is needed -		if need_group then -			if minetest.get_item_group(ciname, need_group) == 0 then +	local get_item_group = minetest.get_item_group +	local group = needed_item:match("^group:(.+)") +	if group then +		if not craft_item:is_empty() then +			-- Source item must be the same to fill +			if get_item_group(craft_item:get_name(), group) ~= 0 then +				needed_item = craft_item:get_name() +			else +				-- TODO: Maybe swap unmatching "craft" items +				-- !! Would conflict with recursive function call  				return  			end -			needed_item = ciname -			need_group = false -		end -	end - -	if need_group then -		-- search an item of the specific group -		for i,item in pairs(player_inv:get_list("main")) do -			if not item:is_empty() -			and minetest.get_item_group(item:get_name(), need_group) > 0 then -				return i +		else +			-- Take matching group from the inventory (biggest stack) +			local main = inv:get_list("main") +			local max_found = 0 +			for i, stack in ipairs(main) do +				if stack:get_count() > max_found and +						get_item_group(stack:get_name(), group) ~= 0 then +					needed_item = stack:get_name() +					max_found = stack:get_count() +					if max_found >= amount then +						break +					end +				end  			end  		end - -		-- no index found -		return -	end - -	-- search an item with a the name needed_item -	for i,item in pairs(player_inv:get_list("main")) do -		if not item:is_empty() -		and item:get_name() == needed_item then -			return i +	else +		if not craft_item:is_empty() and +				craft_item:get_name() ~= needed_item then +			return -- Item must be identical  		end  	end -	-- no index found -end - --- modifies the player inventory and returns the changed craft_item if possible -local function move_item(player_inv, craft_item, needed_item) -	local stackid = item_fits(player_inv, craft_item, needed_item) -	if not stackid then -		return +	needed_item = ItemStack(needed_item) +	local to_take = math.min(amount, needed_item:get_stack_max()) +	to_take = to_take - craft_item:get_count() +	if to_take <= 0 then +		return -- Nothing to do  	end -	local wanted_stack = player_inv:get_stack("main", stackid) -	local taken_item = wanted_stack:take_item() -	player_inv:set_stack("main", stackid, wanted_stack) - -	if not craft_item -	or craft_item:is_empty() then -		return taken_item +	needed_item:set_count(to_take) + +	local taken = inv:remove_item("main", needed_item) +	local leftover = taken:add_item(craft_item) +	if not leftover:is_empty() then +		-- Somehow failed to add the existing "craft" item. Undo the action. +		inv:add_item("main", leftover) +		return taken  	end - -	craft_item:add_item(taken_item) -	return craft_item +	return taken  end  local function craftguide_craft(player, formname, fields) @@ -510,15 +506,21 @@ local function craftguide_craft(player, formname, fields)  		if amount then break end  	end  	if not amount then return end + +	amount = tonumber(amount) or 99 -- fallback for "all" +	if amount <= 0 or amount > 99 then return end +  	local player_name = player:get_player_name() -	local output = unified_inventory.current_item[player_name] -	if (not output) or (output == "") then return end +	local output = unified_inventory.current_item[player_name] or "" +	if output == "" then return end  	local player_inv = player:get_inventory() +	local craft_list = player_inv:get_list("craft") -	local crafts = unified_inventory.crafts_for[unified_inventory.current_craft_direction[player_name]][output] -	if (not crafts) or (#crafts == 0) then return end +	local crafts = unified_inventory.crafts_for[ +		unified_inventory.current_craft_direction[player_name]][output] or {} +	if #crafts == 0 then return end  	local alternate = unified_inventory.alternate[player_name] @@ -526,24 +528,17 @@ local function craftguide_craft(player, formname, fields)  	if craft.width > 3 then return end  	local needed = craft.items - -	local craft_list = player_inv:get_list("craft") -  	local width = craft.width  	if width == 0 then  		-- Shapeless recipe  		width = 3  	end -	amount = tonumber(amount) or 99 -	--[[ -	if amount == "max" then -		amount = 99 -- Arbitrary; need better way to do this. -	else -		amount = tonumber(amount) -	end--]] - -	for iter = 1, amount do +	-- To spread the items evenly +	local STEPSIZE = math.ceil(math.sqrt(amount) / 5) * 5 +	local current_count = 0 +	repeat +		current_count = math.min(current_count + STEPSIZE, amount)  		local index = 1  		for y = 1, 3 do  			for x = 1, width do @@ -551,7 +546,9 @@ local function craftguide_craft(player, formname, fields)  				if needed_item then  					local craft_index = ((y - 1) * 3) + x  					local craft_item = craft_list[craft_index] -					local newitem = move_item(player_inv, craft_item, needed_item) +					local newitem = craftguide_move_stacks(player_inv, +							craft_item, needed_item, current_count) +  					if newitem then  						craft_list[craft_index] = newitem  					end @@ -559,7 +556,7 @@ local function craftguide_craft(player, formname, fields)  				index = index + 1  			end  		end -	end +	until current_count == amount  	player_inv:set_list("craft", craft_list)  | 
