--[[

Craft Guide for Minetest

Copyright (c) 2012 cornernote, Brett O'Donnell <cornernote@gmail.com>
Source Code: https://github.com/cornernote/minetest-craft_guide
License: BSD-3-Clause https://raw.github.com/cornernote/minetest-craft_guide/master/LICENSE

CRAFT GUIDE API

]]--





-- expose object to other modules
craft_guide = {}


--        vvv  INTERNAL SETTINGS  vvv

-- enable or disable you need feature

craft_guide.you_need=true

-- enable or disable copy craft recipe to crafting grid feature

craft_guide.copy_button=true


-- show items which only have have craft recipes of type "fuel". This are for example: tree trunks, saplings, .. etc.
--Don't matter when craft_guide.show_fuel=false

craft_guide.show_all_fuel_crafts=false


-- don't show any recipes of type fuel in craft guide

craft_guide.show_fuel=true


--shows crafts other then normal crafts in crafting grid or of type "cooking" or "fuel".
--at the moment this are crafts for machines from technic mod

craft_guide.other_crafting_types=true


--don't show crafts which are registered in moreblocks mod to get the original item back from its slabs, panels, microblocks, etc...
--and don't show all ingots, dusts and blocks of uranium with different percentages
craft_guide.remove_cluttering_crafts=true


-- here you can define base items for "you need" feature

--all items with this prefix are base items:

craft_guide.basic_item_prefixes = { 

	"dye:",

}

--all items which belong to this groups are base items

craft_guide.basic_item_groups = { 

	"wood",
	"stone",
	"stick",
	"tree",
	"sand",
	"glass",

}

--all items which end with these strings are base items

craft_guide.basic_item_endings = {

	"ingot",
	"lump",
	"glass",
	"dust",

}

-- here you can define single items as base items.
-- items without crafting recipe or items which match criterias from the tables above are base items too.

craft_guide.basic_items	= { 

	"default:dirt",
	"default:sand",
	"default:cobble",
	"default:snowblock",
	"default:ice",
	"default:wood",
	"default:stone",
	"default:stick",
	"default:clay_brick",
	"default:gravel",
	"default:mossycobble",
	"default:desert_stone",
	"default:desert_cobble",
	"default:desert_sand",
	"default:diamond",
	"default:mese_crystal",
	"default:glass",
	"default:obsidian",
	"default:wheat",
	"bucket:bucket_water",
	"bucket:bucket_lava",
	"technic:uranium",
	"technic:raw_latex",
	"homedecor:roof_tile_terracotta",
	"homedecor:terracotta_base",
	"mesecons_materials:glue",
	"wool:white"
}

-- END OF SETTINGS SECTION




-- define api variables
craft_guide.crafts = {}

craft_guide.alias = {}

craft_guide.fuel = {}

craft_guide.saved_you_need_lists = {}

craft_guide.you_need_list = {}

craft_guide.add_things=true

craft_guide.fuel_to_add=false

-- log
craft_guide.log = function(message)
	--if not craft_guide.DEBUG then return end
	minetest.log("action", "[CraftGuide] "..message)
end


-- register_craft
craft_guide.register_craft = function(options)
	if  options.type == "fuel" and craft_guide.show_fuel and options.recipe~=nil then
		local itemstack = ItemStack(options.recipe)
		if itemstack:is_empty() then
			return
		end

		if craft_guide.fuel[itemstack:get_name()]==nil then
			craft_guide.fuel[itemstack:get_name()] = {}
		end
		table.insert(craft_guide.fuel[itemstack:get_name()],options)
		craft_guide.fuel_to_add=true
		return 
	end

	if  options.output == nil then
		return
	end
	local itemstack = ItemStack(options.output)
	if itemstack:is_empty() then
		return
	end
	--this should remove crafts which craft original item back from stairs, slabs, panels or micros, 
	if craft_guide.remove_cluttering_crafts then
		local mod,_=string.find(itemstack:get_name(),":")
		if mod~=nil then
			mod=string.sub(itemstack:get_name(),1,mod)
			local recipestr=""
			if options.recipe[1]~=nil and type(options.recipe[1])=="string" then
				recipestr=" "..options.recipe[1]
			elseif options.recipe[1]~=nil and type(options.recipe[1][1])=="string" then
				recipestr=" "..options.recipe[1][1]
			elseif options.recipe[2]~=nil and type(options.recipe[2][1])=="string" then
				recipestr=" "..options.recipe[2][1]
			end
			if 			
				--dont show recipes for ingots, dusts and blocks of uranium with different percentages
				string.find(itemstack:get_name(),"technic:uranium._")==nil  
				and string.find(itemstack:get_name(),"technic:uranium.._")==nil
				and 

				(recipestr==""or (options.recipe~=nil and string.find(recipestr," "..mod.."panel_")==nil 
				and string.find(recipestr," "..mod.."stair_")==nil
				and string.find(recipestr," "..mod.."micro_")==nil  and string.find(recipestr," "..mod.."slab_")==nil
				and string.find(recipestr," moreblocks:panel_")==nil and string.find(recipestr," moreblocks:stair_")==nil
				and string.find(recipestr," moreblocks:micro_")==nil  and string.find(recipestr," moreblocks:slab_")==nil)) then


				--craft_guide.log("registered craft for - "..itemstack:get_name())
				if craft_guide.crafts[itemstack:get_name()]==nil then
					craft_guide.crafts[itemstack:get_name()] = {}
				end
			table.insert(craft_guide.crafts[itemstack:get_name()],options)
			end
		end

	end
end


-- register_alias
craft_guide.register_alias = function(alias,convert_to)
	local count=#craft_guide.alias
	craft_guide.alias[count+1]=alias
	craft_guide.alias[count+2]=convert_to
end

-- get_craft_guide_formspec
craft_guide.get_craft_guide_formspec = function(meta, search, page, alternate)
	if craft_guide.add_things then
		craft_guide.add_additional_crafts()
	end
	if search == nil then 
		search = meta:get_string("search")
	end
	if meta:get_string("formspec")=="" then
		meta:set_string("owner","")
		meta:set_string("saved_search","|")
		meta:set_string("saved_page","1")
		meta:set_string("saved_pages","1")
		meta:set_string("switch","bookmarks")
		meta:set_string("poslist","down")
		meta:set_string("globalcount","1")
		meta:set_string("time","0")
		meta:set_string("method","Cook")
		meta:set_string("locked","0")
		meta:set_string("isowner","0")
	end	
	if page == nil then 
		page = craft_guide.get_current_page(meta) 
	end
	if alternate == nil then 
		alternate = craft_guide.get_current_alternate(meta) 
	end
	local inv = meta:get_inventory()
	local size = inv:get_size("main")
	local start = (page-1) * (5*14) --was 1 too much before
	local pages = math.floor((size-1) / (5*14) + 1)
	local alternates = 0
	local stack = inv:get_stack("output",1)
	local crafts = craft_guide.crafts[stack:get_name()]
	if crafts ~= nil then
		alternates = #crafts
	end
	local backbutton=""
	if meta:get_string("saved_search")~="|" then
		backbutton="button[6.3,5.8;2.7,1;back_button;<--- Back]"
	end
	local changeable_part=""
	if meta:get_string("switch")=="youneed" and craft_guide.you_need then
		changeable_part="button[9.7,6.35;0.8,0.7;switch_to_bookmarks;>>]"
				.."tooltip[switch_to_bookmarks;Show your saved bookmarks]"
		if meta:get_string("poslist")=="down" then
			changeable_part= changeable_part.."label[8,6.5;You need:]"
				.."button[10.42,6.35;0.5,0.7;move_up;^]"
				.."tooltip[move_up;Move the list of needed items upwards]"
				.."label[11.4,6.0;Add to]"
				.."label[11.2,6.35;bookmarks]"
				.."label[12.6,6.05;->]"
				.."list[current_name;add;13,6;1,1;]"
				..craft_guide.build_button_list(meta,inv,"youneed",12,29,8,7,6)

		else
			changeable_part= changeable_part.."button[10.42,6.35;0.5,0.7;move_down;v]"
				.."tooltip[move_down;Move the list of needed items downwards]"
				..craft_guide.build_button_list(meta,inv,"youneed",12,29,0,1,14,0)
		end
		changeable_part= changeable_part..craft_guide.get_amounts(meta,inv,"youneed")

	end
 	if meta:get_string("switch")=="bookmarks" or (not craft_guide.you_need) or meta:get_string("poslist")=="up" then

		changeable_part= changeable_part.."label[8,6.5;Bookmarks]"
		if craft_guide.you_need and meta:get_string("switch")=="bookmarks" then
			changeable_part= changeable_part.."button[9.7,6.35;0.8,0.7;switch_to_youneed;>>]"
			.."tooltip[switch_to_youneed;Show amount of basic items needed]"
		end
		changeable_part= changeable_part.."list[current_name;bookmark;8,7;6,3;]"
			.."label[12,6.1;Bin ->]"
			.."list[current_name;bin;13,6;1,1;]"
	end

	local formspec = "size[14,10;]"
	if meta:get_string("switch")=="youneed" and meta:get_string("poslist")=="up" then
		formspec=formspec.."label[0.1,0.3;You need:]"
	else
		formspec=formspec.."list[current_name;main;0,0;14,5;"..tostring(start).."]"
	end
	formspec=formspec.."label[0,5;--== Learn to Craft ==--]"

		.."label[0,5.4;Drag any item to the Output box to see the]"
		.."label[0,5.8;craft. Save your favorite items in Bookmarks.]"

		.."field[6,5.4;2.3,1;craft_guide_search_box;;"..tostring(search).."]"
		.."button[7.8,5.1;1.2,1;craft_guide_search_button;Search]"
		..backbutton
		.."label[9.1,5.2;page "..tostring(page).." of "..tostring(pages).."]"
		.."button[11,5;1.5,1;craft_guide_prev;<<]"
		.."button[12.5,5;1.5,1;craft_guide_next;>>]"

		if inv:get_stack("fuel",1)==nil or inv:get_stack("fuel",1):get_name()==nil or inv:get_stack("fuel",1):get_name()=="" then
			formspec=formspec.."label[0,6.5;Output]"
		end
		formspec=formspec.."list[current_name;output;0,7;1,1;]"

		.."label[2,6.5;Inventory Craft]"
		if not (inv:get_stack("additional",1)==nil or inv:get_stack("additional",1):get_name()==nil 
			or inv:get_stack("additional",1):get_name()=="") then
			formspec=formspec.."list[current_name;additional;0.96,7;1,1;]"
		end
		formspec=formspec..craft_guide.build_button_list(meta,inv,"build",3,11,2,7,3)
		if not (inv:get_stack("cook",1)==nil or inv:get_stack("cook",1):get_name()==nil or inv:get_stack("cook",1):get_name()=="")
			or (inv:get_stack("fuel",1)==nil or inv:get_stack("fuel",1):get_name()==nil or inv:get_stack("fuel",1):get_name()=="") then
			formspec=formspec.."label["..tostring(6.22-string.len(meta:get_string("method"))*0.05)..",6.5;"..meta:get_string("method").."]"
			if not (inv:get_stack("cook",2)==nil or inv:get_stack("cook",2):get_name()==nil or inv:get_stack("cook",2):get_name()=="") then
				formspec=formspec..craft_guide.build_button_list(meta,inv,"cook",1,2,5.5,7,2)
			else
				formspec=formspec..craft_guide.build_button_list(meta,inv,"cook",1,1,6,7,1)
			end
		end
		--add flames from default mod for craft fuel
		if not (inv:get_stack("fuel",1)==nil or inv:get_stack("fuel",1):get_name()==nil or inv:get_stack("fuel",1):get_name()=="") then
			formspec=formspec.."label[6,6.5;Fuel]"
			..craft_guide.build_button_list(meta,inv,"fuel",1,1,6,7,1)
			.."image[6.13,9.1;0.7,0.7;default_furnace_fire_fg.png]"
			if meta:get_string("time")~=nil and meta:get_string("time")~="nil" then	
				formspec=formspec.."label[6.02,8.17;"..meta:get_string("time").." sec]"
			end
		end
		if not (inv:get_stack("cook",1)==nil or inv:get_stack("cook",1):get_name()==nil or inv:get_stack("cook",1):get_name()=="") then
			formspec=formspec.."list[current_name;machine;6,9;1,1;]"
			if meta:get_string("time")~=nil and meta:get_string("time")~="nil" then	
				formspec=formspec.."label[6.02,8.17;"..meta:get_string("time").." sec]"
			end
		end
	if alternates > 1 then
		if alternate>alternates then
			alternate=1	
		end
		formspec = formspec
			.."label[0,8;recipe "..tostring(alternate).." of "..tostring(alternates).."]"
			.."button[0,8.4;2,1;alternate;Alternate]"

	end

		if craft_guide.copy_button 
			and inv:get_stack("output",1)~=nil and inv:get_stack("output",1):get_name()~=nil and inv:get_stack("output",1):get_name()~=nil then
			if craft_guide.crafts[inv:get_stack("output",1):get_name()]~=nil then
				if craft_guide.crafts[inv:get_stack("output",1):get_name()][alternate]~=nil then
					if (craft_guide.crafts[inv:get_stack("output",1):get_name()][alternate]).type==nil
						or (craft_guide.crafts[inv:get_stack("output",1):get_name()][alternate]).type=="shapeless" then
						formspec=formspec.."label[5.45,8.6;Prepare to craft:]"
						.."button[5.6,9.2;0.7,0.8;copy1;1]"
						.."button[6.2,9.2;0.7,0.8;copy10;10]"
						.."button[6.8,9.2;0.7,0.8;copy99;99]"
					end
				end
			end
		end
		formspec=formspec..changeable_part
		.."button_exit[0,9.2;1,0.8;close_mm;ESC]"


	meta:set_string("saved_formspec",formspec)
	--this needs to be added last, so it can be changed when restoring a locked formspec
	if meta:get_string("isowner")=="1" then
		if meta:get_string("locked")=="0" then
			formspec=formspec.."button[0.88,9.2;1.22,0.8;lock;Lock]"
				.."tooltip[lock;Lock Craft Guide in current state]"
		else
			formspec=formspec.."button[0.88,9.2;1.22,0.8;lock;Locked]"
				.."tooltip[lock;Craft Guide is locked - Press again to unlock]"
		end
	else
		if meta:get_string("locked")~="0" and meta:get_string("owner")~=nil and meta:get_string("owner")~="" then
			formspec=formspec.."label[0.88,9.2;Locked]"
				.."tooltip[close_mm;   Owner: "..meta:get_string("owner").."]"
		end
	end


	return formspec
end


-- on_construct
craft_guide.on_construct = function(pos)
	local meta = minetest.env:get_meta(pos)
	local inv = meta:get_inventory()
	inv:set_size("output", 1)
	inv:set_size("additional", 1) --here goes the second output of centrifuge recipe, just shown when needed
	inv:set_size("build", 3*3)
	inv:set_size("cook", 2*1)
	inv:set_size("fuel", 1)
	inv:set_size("machine", 1)
	inv:set_size("bookmark", 6*3)
	inv:set_size("youneed", 6*15)
	inv:set_size("bin", 1)
	inv:set_size("add", 1)
	inv:set_size("copylist", 9)
	inv:set_size("tempinv", 42)
	inv:set_size("tempmain", 32)
	inv:set_size("tempresult", 1)
	if meta:get_string("locked")~="1" then
		craft_guide.create_inventory(inv)
	end
	meta:set_string("formspec",craft_guide.get_craft_guide_formspec(meta))
	meta:set_string("out","")
	meta:set_string("addindex","1")
end


-- on_receive_fields
craft_guide.on_receive_fields = function(pos, formname, fields, player)
	local meta = minetest.env:get_meta(pos);
	if meta:get_string("locked")=="1" then
		craft_guide.save_meta(meta)
	end
	if minetest.get_node(pos).name=="craft_guide:sign_wall_locked" or minetest.get_node(pos).name=="craft_guide:lcd_pc_locked" then
		if meta:get_string("owner")=="" then
			meta:set_string("owner",player:get_player_name())
			meta:set_string("isowner","1")
		elseif meta:get_string("owner")==player:get_player_name() then
			meta:set_string("isowner","1")
		end
	end
	local inv = meta:get_inventory()
	if inv:get_size("additional")==nil or inv:get_size("additional")~=1 then  --old version, construct again
		local node=minetest.get_node(pos)
		minetest.set_node(pos, node)
		meta = minetest.env:get_meta(pos)
		inv = meta:get_inventory()
	end
	if inv:get_size("copylist")==nil or inv:get_size("copylist")~=9 then  
	inv:set_size("copylist", 9)
	inv:set_size("tempinv", 42)
	inv:set_size("tempmain", 32)
	inv:set_size("tempresult", 1)
	end
	local size = inv:get_size("main",1)
	local stack = inv:get_stack("output",1)
	local crafts = craft_guide.crafts[stack:get_name()]
	local alternate = craft_guide.get_current_alternate(meta)
	local alternates = 0
	if crafts ~= nil then
		alternates = #crafts
	end

	local page = craft_guide.get_current_page(meta)
	local pages = math.floor((size-1) / (5*14) + 1)

	
	-- search
	local update_search=false
	local search
	search = fields.craft_guide_search_box
	if search~=nil then
		if string.lower(search)==string.upper(search) and tonumber(search)==nil and search~="*" then
			search=""
		end
		update_search=true
	else
			search=meta:get_string("search")
	end
	meta:set_string("search", search)
	if fields.craft_guide_search_button then
		if search==nil then
			meta:set_string("search", "")
		end
		if meta:get_string("switch")=="youneed" and meta:get_string("poslist")=="up" then
			meta:set_string("switch","bookmarks")
		end		
		meta:set_string("saved_search", "|")
		page = 1
		update_search=true
	end

	-- copy buttons:

	local copy=0
	if fields.copy99 then
		copy=99
	elseif fields.copy10 then
		copy=10
	elseif fields.copy1 then
		copy=1
	end
	if copy~=0 and player~=nil then
		local inv2=player:get_inventory()
		if inv2~=nil then
			for i=0,inv:get_size("copylist"),1 do
				inv:set_stack("copylist",i,ItemStack(nil))
			end
			for i=0,inv:get_size("build"),1 do
				local stk=inv:get_stack("build", i)
				if stk:get_count()>0 then
					if string.sub(stk:get_name(),1,6)=="group:" then
						inv:set_stack("copylist",i,ItemStack(stk:get_name().."~|@q 1"))
					else
						inv:add_item("copylist",ItemStack(stk:get_name().."~|@q 1")) --trick, because stacksize of unknown items is 99
					end
				end
			end
			inv:set_list("tempinv",inv2:get_list("main"))
			for i=0,inv2:get_size("craft"),1 do
				local st=inv2:get_stack("craft",i)
				if st:get_count()>0 then
					inv:add_item("tempinv",st)
				end
			end
			local st=inv2:get_stack("craftresult",1)
			if st:get_count()>0 then
				inv:add_item("tempinv",st)
			end
			for i=0,inv:get_size("copylist"),1 do
				local stk=inv:get_stack("copylist", i)
				local stkcount=stk:get_count()
				if stkcount>0 then
					local stkname=stk:get_name()
					if string.sub(stkname,1,6)~="group:" then
						stk=ItemStack(string.sub(stkname,1,string.len(stkname)-4).." "..tostring(stkcount*copy))
						inv:set_stack("copylist",i,ItemStack(nil))
						local lastcheck=0
						local removed=0
						for x=1,9,1 do
							if stk:get_count()>stk:get_stack_max()+removed then
								stk=ItemStack(stk:get_name().." "..tostring(stk:get_stack_max()))
							else
								lastcheck=1
							end
							removed=removed+(inv:remove_item("tempinv",stk)):get_count()
							if lastcheck==1 or not (inv:contains_item("tempinv",ItemStack(stk:get_name().." 1"))) then
								break
							end
						end
						if copy>math.floor(removed/stkcount) then
							inv:add_item("tempinv",ItemStack(stk:get_name().." "..tostring(removed-(math.floor(removed/stkcount)*stkcount))))
							for jj=0,i-1,1 do
								local oldstack=inv:get_stack("copylist", jj)
								if oldstack:get_count()>0 and string.sub(oldstack:get_name(),1,6)~="group:"then
									local newstack=ItemStack(oldstack:get_name().." "..tostring((copy-math.floor(removed/stkcount))*oldstack:get_count()))
									inv:add_item("tempinv", newstack)
								end
							end
							copy=math.floor(removed/stkcount)
						end
						lastcheck=0
						if copy<1 then
							break
						end
							
					end
				end
			end
			if copy>0 then
			for i=0,inv:get_size("copylist"),1 do
				local stk=inv:get_stack("copylist", i)
				local stkcount=stk:get_count()
				if stkcount>0 then
					local stkname=stk:get_name()
					if string.sub(stkname,1,6)=="group:" then
						local success=false
						local groups=string.sub(stkname,7,string.len(stkname)-4)
						for count=copy,0,-1 do
							for i2=0,inv:get_size("tempinv"),1 do
								local check=inv:get_stack("tempinv",i2)
								if check:get_count()>0 then
									local name=check:get_name()
									local hasgroup=1
									for group in string.gmatch(groups,"([^,]+)") do
										if minetest.get_item_group(name, group)==0 then
											hasgroup=0
											break
										end
									end
									if hasgroup==1 then
	
										if inv:contains_item("tempinv",ItemStack(name.." "..tostring(count))) then	
											inv:remove_item("tempinv",ItemStack(name.." "..tostring(count)))
											inv:set_stack("copylist",i,ItemStack(name.." 1"))
											success=true
											break
										end
									end
								end
							end
							if copy>count then
								for jj=0,i-1,1 do
									local oldstack=inv:get_stack("copylist", jj)
									if oldstack:get_count()>0 and string.sub(oldstack:get_name(),1,6)~="group:" then
										local newstack=ItemStack(oldstack:get_name().." "..tostring((copy-count)*oldstack:get_count()))
										inv:add_item("tempinv", newstack)
									end
								end
								copy=count
							end
							if success or count<1 then
								break
							end

						end
					end
				end
				if copy<1 then
					break
				end
			end
			end
			if copy>0 then
				for i=0,inv:get_size("build"),1 do 
					local stk=inv:get_stack("build", i)
					local stkcount=stk:get_count()
					if stkcount>0 then
						local stkname=stk:get_name()
						if string.sub(stkname,1,6)=="group:" then
							stk=inv:get_stack("copylist", i)
							stkname=stk:get_name()
						end

						stk=ItemStack(stkname.." "..tostring(copy))
						inv:set_stack("copylist",i,stk)
					end
				end

				local clean=1
				if copy>0 then
					for i=0,inv:get_size("tempmain"),1 do
						inv:set_stack("tempmain",i,ItemStack(nil))
					end

					local stk=inv2:get_stack("craftresult", 1)
					if stk:get_count()>0 then
						if inv:contains_item("tempinv",stk) then
							inv:remove_item("tempinv",stk)
							inv:add_item("tempresult",1,stk)
						else 
							inv:add_item("tempresult",1,ItemStack(nil))
						end
					end
					for i=0,inv2:get_size("main"),1 do --restore players main inventory
						local stk=inv2:get_stack("main", i)
						if stk:get_count()>0 then
							local removed=(inv:remove_item("tempinv",stk)):get_count()
							if removed>0 then
								inv:set_stack("tempmain",i,ItemStack(stk:get_name().." "..tostring(removed)))
							end
						end
					end
					for i=0,inv:get_size("tempinv"),1 do --check if items left in crafting grid can be moved to players inventory
						local stk=inv:get_stack("tempinv", i)
						if stk:get_count()>0 then
							if inv:room_for_item("tempmain",stk) then
								inv:add_item("tempmain",stk)
								inv:set_stack("tempinv",i,ItemStack(nil))
							else 
								clean=0
							end
						end
					end
					if clean==0 then
						local free=0
						for i=0,inv:get_size("tempmain"),1 do --check if two small stacks of same item can be joined to one big stack
							local stk=inv:get_stack("tempmain", i)
							if stk:get_count()>0 then
								if inv:room_for_item("tempmain",ItemStack(stk:get_name().." "..tostring(stk:get_stack_max()*(1+free)))) then
									inv:set_stack("tempmain",i,ItemStack(nil))
									inv:add_item("tempmain",stk)
									free=free+1
								end
							end
						end
						for i=0,inv:get_size("build"),1 do --try to move more items to crafting grid
							local stk=inv:get_stack("build", i)
							local stkcount=stk:get_count()
							if stkcount>0 then
								local stkname=stk:get_name()
								stk=ItemStack(stkname.." 1")
								local stkmax=ItemStack(stkname.." "..tostring(stk:get_stack_max()-copy))
								if inv:contains_item("tempinv",stk) then
									local removed=inv:remove_item("tempinv",stkmax)
									inv:set_stack("copylist",i,ItemStack(stkname.." "..tostring(removed:get_count()+copy)))
								elseif inv:contains_item("tempmain",stk) then
									local removed=inv:remove_item("tempmain",stkmax)
									inv:set_stack("copylist",i,ItemStack(stkname.." "..tostring(removed:get_count()+copy)))
								end
							end
						end

						for i=0,inv:get_size("tempinv"),1 do --last try to place all left items in main inventory
							local stk=inv:get_stack("tempinv", i)
							if stk:get_count()>0 then
								if inv:room_for_item("tempmain",stk) then
									inv:add_item("tempmain",stk)
									inv:set_stack("tempinv",i,ItemStack(nil))
								else 
									minetest.chat_send_player(player:get_player_name(), "Can't copy this recipe to crafting grid because your inventory is too full to move items around!")

									copy=0
									break
								end
							end
						end
					end
					if copy>0 then --we can successfully craft some of this item
						for i=0,inv:get_size("copylist"),1 do 
							local stk=inv:get_stack("copylist", i)
							local stkcount=stk:get_count()
							if stkcount>copy then --if possible remove additional items back to inventory
								stk=ItemStack(stk:get_name().." 1")
								if inv:room_for_item("tempmain",stk) then
									local left=inv:add_item("tempmain",ItemStack(stk:get_name().." "..tostring(stkcount-copy)))
									if left~=nil and left~=0 then 
										inv:set_stack("copylist", i,ItemStack(stk:get_name().." "..tostring(copy+left:get_count())))	
									end
									
								end
							end
						end
	
						--add wear and metadata to items again
						for t=0,42,1 do 
							local tx=-10
							local invlist="tempmain"
							if t<=9 then
								invlist="copylist"
								tx=0							
							end
							local itemStack=inv:get_stack(invlist, tx+t)
							if itemStack:get_count()==1 then
								if itemStack:get_stack_max()==1 then
									local itempos=t
									local found=false
									local itemStack2=ItemStack(nil)
									for slot=0,42,1 do
										if slot<=9 then
											itemStack2=inv2:get_stack("craft", slot)
											if itemStack2:get_name()==itemStack:get_name() then
												found=true
											end
										else
											itemStack2=inv2:get_stack("main", slot-10)
											if itemStack2:get_name()==itemStack:get_name() then
												found=true
											end
										end
										if found then
											found=false
											inv:set_stack(invlist, t+tx,itemStack2)
											for tt=itempos+1,42,1 do
												if tt<=9 then
													itemStack2=inv:get_stack("copylist", tt)
													if itemStack2:get_name()==itemStack:get_name() then
														itemStack=inv2:get_stack("copylist", tt)
														itempos=tt
														break
													end
												else
													itemStack2=inv:get_stack("tempmain",tt-10)
													if itemStack2:get_name()==itemStack:get_name() then
														itemStack=inv:get_stack("tempmain", tt-10)
														itempos=tt
														break
													end
												end
											end
										end
									end	
								end
							end
						end
						--copy tempinventory to real inventory
						inv2:set_list("craft",inv:get_list("copylist"))
						inv2:set_list("main",inv:get_list("tempmain"))
						inv2:set_list("craftresult",inv:get_list("tempresult"))
					
					end				
				end
			end
		end
	end

	
	-- change page
	if fields.craft_guide_prev then
		page = page - 1
		if page < 1 then
			page = pages
		end
		if meta:get_string("switch")=="youneed" and meta:get_string("poslist")=="up" then
			meta:set_string("switch","bookmarks")
		end
	end

	if fields.craft_guide_next then
		page = page + 1
		if page > pages then
			page = 1
		end
		if meta:get_string("switch")=="youneed" and meta:get_string("poslist")=="up" then
			meta:set_string("switch","bookmarks")
		end
	end

	if page > pages then
		page = pages
	end

	if page < 1 then
		page = 1
	end

	-- go back to search result
	if fields.back_button then
		if meta:get_string("switch")=="youneed" and meta:get_string("poslist")=="up" then
			meta:set_string("switch","bookmarks")
		end		
		local saved_search = meta:get_string("saved_search")
		if saved_search~="|" then
			search=saved_search
			meta:set_string("search", saved_search)
			page=tonumber(meta:get_string("saved_page"))
			pages=tonumber(meta:get_string("saved_pages"))
			meta:set_string("saved_search", "|")
		end
		update_search=true
	end

	--lock current state
	if fields.lock and meta:get_string("owner")==player:get_player_name() then	
		if meta:get_string("locked")=="2" then
			meta:set_string("locked","0")
		else
			meta:set_string("locked","1")
		end
	end


	--toogle between bookmarks/you need
	if fields.switch_to_bookmarks then	
		meta:set_string("switch","bookmarks")
	end

	if fields.switch_to_youneed then	
		meta:set_string("switch","youneed")
		craft_guide.update_recipe(meta, player, stack, alternate)
	end

	--replacing bookmarks or main item list?
	if fields.move_up then	
		if meta:get_string("switch")=="youneed" then
			meta:set_string("poslist","up")
			if meta:get_string("locked")~="0" then
				craft_guide.update_recipe(meta, player, stack, alternate)
			end
		end
	end

	if fields.move_down then	
		if meta:get_string("switch")=="youneed" then
			meta:set_string("poslist","down")
			if meta:get_string("locked")~="0" then
				craft_guide.update_recipe(meta, player, stack, alternate)
			end
		end
	end


	-- get an alternate recipe
	if fields.alternate then
		alternate = alternate+1
		craft_guide.update_recipe(meta, player, stack, alternate)
	end
	if alternate > alternates then
		alternate = 1
	end

	--group buttons, finally a solution with a for loop
	local starts=""
	local ends=""
	local xx=""
	local formspec = meta:get_string("formspec")
	for button_number=1,29,1 do
		if fields[("t_758s"..tostring(button_number))] then 
			--search the group name of pressed group button directly in formspec string
			xx,starts=string.find(formspec,"tooltip%[t_758s"..tostring(button_number)..";")
			if starts~=nil then
				ends,xx=string.find(formspec,"%]",starts+1)
				local group=string.lower(string.sub(formspec,starts+1,ends-2))
				--displaying of items in a group is implemented in search function, just need to set search string
				meta:set_string("search", "group:"..group)
				--save old search string for restoring when "<-- back" is pressed
				if meta:get_string("saved_search")=="|" then
					meta:set_string("saved_search", search)
					meta:set_string("saved_page", tostring(page))
					meta:set_string("saved_pages", tostring(pages))
				end
				page = 1
				search="group:"..group
				update_search=true
			end
		break
		end
	end
	if starts~="" and meta:get_string("switch")=="youneed" and meta:get_string("poslist")=="up" then --button pressed, need to move back to bookmarks
		meta:set_string("switch","bookmarks")
	end
	-- update the formspec
	if meta:get_string("locked")=="2" and (fields["quit"] or fields.close_mm) then
		craft_guide.restore_meta(meta)
	else
		if update_search then
			craft_guide.create_inventory(inv, search)
		end
		meta:set_string("formspec",craft_guide.get_craft_guide_formspec(meta, search, page, alternate))
		if meta:get_string("locked")=="1" then
			craft_guide.save_meta(meta)		
		end
	end
end


-- returns formspec string of a inventory list with buttons for group items
craft_guide.build_button_list = function(meta,inv,list,start_index,end_index,x,y,w,show_empty)
	--button numbers go from start_index to end_index
	--button numbers 1,(2)= cook or fuel
	--button numbers 3-11= inventory craft field
	--button numbers 12-29= you need items
	if show_empty~=0 then
		show_empty=1
	end
	local string=""
	for i=1,end_index-start_index+1,1 do
		local string_old=string
		local stack = inv:get_stack(list,i)
		if stack~=nil then
			local name=stack:get_name()
			if string.sub(name,1,6)=="group:" then
				local groups=string.sub(name,7)
				local saved=""
				for name,def in pairs(minetest.registered_items) do
					local hasgroup=1
					for group in string.gmatch(groups,"([^,]+)") do
						if minetest.get_item_group(name, group)==0 then
							hasgroup=0
						end
					end
					if hasgroup==1 then

                                                --prefer items from default mod
						if string.sub(name,1,8)=="default:" then
							--prefer items with simple short names, because cnc machines adds items under default prefix too
							if string.len(name)<20 then 
								string=string.."item_image_button["..tostring(x+((i-1)%w))..","
								..tostring(y+math.floor((i-1)/w))..";1,1;"
								..name..";t_758s"..tostring(i+start_index-1)..";group]"
								.."tooltip[t_758s"..tostring(i+start_index-1)..";"
								..string.upper(string.sub(groups,1,1))..string.sub(groups.." ",2).."]"
	
								saved=""
								break
							end
						elseif saved=="" then
							saved=name
						end
					end
				end
				if saved~="" then
					string=string.."item_image_button["..tostring(x+((i-1)%w))..","
					..tostring(y+math.floor((i-1)/w))..";1,1;"..saved..";t_758s"..tostring(i+start_index-1)..";group]"
					.."tooltip[t_758s"..tostring(i+start_index-1)..";"
					..string.upper(string.sub(groups,1,1))..string.sub(groups.." ",2).."]"
				end
			end
		end

		if string_old==string and ((stack~=nil and stack:get_name()~="") or show_empty==1) then
			string=string.."list[current_name;"..list..";"..tostring(x+((i-1)%w))..","..tostring(y+math.floor((i-1)/w))
				..";1,1;"..tostring(i-1).."]"
		end
	end
	return string
end


-- returns a formspec string with item amounts
craft_guide.get_amounts = function(meta,inv,list)
	local amounts=""
	local xx=8.1
	local yy=7.45
	local w=6
	local size=18
	if meta:get_string("poslist")=="up" then
		xx=0.1
		yy=1.45
		w=14
		size=70
	end
	for jj=1,size,1 do
		local item=string.lower(inv:get_stack(list,jj):get_name())
		local cnt=meta:get_string("globalcount")
		if item==nil or item=="" then
			break
		end
		local count=craft_guide.you_need_list[item]
		if count~=nil then
			cnt=math.floor(((count)/tonumber(meta:get_string("globalcount")))*1000+0.49)/1000
			if cnt>1000 then
				cnt=math.floor(cnt+0.49)
			elseif cnt>100 then
				cnt=math.floor(cnt*10+0.49)/10
			elseif cnt>10 then
				cnt=math.floor(cnt*100+0.49)/100
			end
			amounts=amounts.."label["..tostring(xx+((jj-1)%w))..","..tostring(yy+math.floor((jj-1)/w))..";"..tostring(cnt).."]"
		end
		jj=jj+1
		if jj > size then
			break
		end

	end
	return amounts
end


-- get_current_page
craft_guide.get_current_page = function(meta)
	local formspec = meta:get_string("formspec")
	local page = string.match(formspec, "label%[[%d.]+,[%d.]+;page (%d+) of [%d.]+%]")
		page = tonumber(page) or 1
	return page
end


-- get_current_alternate
craft_guide.get_current_alternate = function(meta)
	local formspec = meta:get_string("formspec")
	local alternate = string.match(formspec, "label%[[%d.]+,[%d.]+;recipe (%d+) of [%d.]+%]")
	alternate = tonumber(alternate) or 1
	return alternate
end


-- update_recipe
craft_guide.update_recipe = function(meta, player, stack, alternate)
	local globalcount=1
	local list={}
	local list2={}
	local test={}
	local forlist={}
	local inv = meta:get_inventory()

	for i=0,inv:get_size("build"),1 do
		inv:set_stack("build", i, nil)
	end
	for i=0,inv:get_size("youneed"),1 do
		inv:set_stack("youneed", i, nil)
	end

	inv:set_stack("cook", 1, nil)
	inv:set_stack("cook", 2, nil)

	inv:set_stack("fuel", 1, nil)
	inv:set_stack("machine", 1, nil)
	inv:set_stack("additional", 1, nil)

	meta:set_string("method","Cook")

	if stack==nil then return end
	inv:set_stack("output", 1, stack:get_name())
	if alternate==nil then
		alternate=craft_guide.get_current_alternate(meta)
	end
	alternate = tonumber(alternate) or 1
	local crafts = craft_guide.crafts[stack:get_name()]
	if crafts == nil then
		if stack:get_name()~=nil and stack:get_name()~="" then
			minetest.chat_send_player(player:get_player_name(), "no recipe available for "..stack:get_name())
		end
		meta:set_string("formspec",craft_guide.get_craft_guide_formspec(meta))
		return
	end
	if alternate < 1 or alternate > #crafts then
		alternate = 1
	end
	if stack:get_name()~=nil and stack:get_name()~="" then
		if meta:get_string("switch")=="youneed" then
			craft_guide.log(player:get_player_name().." shows needed items for recipe "..alternate.." for "..stack:get_name())
		else
			craft_guide.log(player:get_player_name().." requests recipe "..alternate.." for "..stack:get_name())
		end
	end	
	local craft = crafts[alternate]
	
	-- show me the unknown items

	--craft_guide.log(dump(craft))

	--minetest.chat_send_player(player:get_player_name(), "recipe for "..stack:get_name()..": "..dump(craft))
	
	local itemstack = ItemStack(craft.output)
	inv:set_stack("output", 1, itemstack)

	if craft.type~=nil and craft.type~="shapeless" and craft.type~="fuel" then
		-- cook
		if craft.type=="cooking" then
			if craft.cooktime==nil then
				meta:set_string("time","3")
			else
				meta:set_string("time",tostring(craft.cooktime))
			end
			inv:set_stack("cook", 1, craft.recipe)
		if minetest.get_modpath("default") then
			inv:set_stack("machine", 1, ItemStack("default:furnace"))
		end
		else
		-- custom types added by technic mod
			local input={}
			if type(craft.input)~="table" or craft.input[1]==nil or craft.input[1]=="" then
				table.insert(input,craft.input)
			else 
				input=craft.input
			end
			if type(input)~="table" or input[1]==nil or input[1]=="" then
				input={}
				table.insert(input,craft.input)
			end

			if craft.type=="Grinder" then
				inv:set_stack("machine", 1, ItemStack("technic:lv_grinder"))
				inv:set_stack("cook", 1, input[1])
			
			elseif craft.type=="Extractor" then
				inv:set_stack("machine", 1, ItemStack("technic:extractor"))
				inv:set_stack("cook", 1, input[1])

			elseif craft.type=="Compressor" then
				inv:set_stack("machine", 1, ItemStack("technic:compressor"))
				inv:set_stack("cook", 1, input[1])

			elseif craft.type=="Alloy Furnace" then
				inv:set_stack("machine", 1, ItemStack("technic:lv_alloy_furnace"))
				inv:set_stack("cook", 1, craft.input[2])
				inv:set_stack("cook", 2, craft.input[1])

			elseif craft.type=="Centrifuge" then
				inv:set_stack("machine", 1, ItemStack("technic:mv_centrifuge"))
				inv:set_stack("cook", 1, input[1])
				inv:set_stack("additional", 1, craft.output2)
			end

			meta:set_string("method",craft.type)
			meta:set_string("time",tostring(craft.time))
			meta:set_string("globalcount",tostring(ItemStack(craft.output):get_count()))
		end
		
	else
	-- fuel
		if craft.type == "fuel" then
			meta:set_string("time",tostring(craft.burntime))
			itemstack=ItemStack(craft.recipe)
			inv:set_stack("output", 1, meta:get_string("out"))
			inv:set_stack("fuel", 1, craft.recipe)
		else
	
			-- build (shaped or shapeless)
			if craft.recipe[1] then
				if (type(craft.recipe[1]) == "string") then
					inv:set_stack("build", 1, craft.recipe[1])
				else
					if craft.recipe[1][1] then
						inv:set_stack("build", 1, craft.recipe[1][1])
					end
					if craft.recipe[1][2] then
						inv:set_stack("build", 2, craft.recipe[1][2])
					end
					if craft.recipe[1][3] then
						inv:set_stack("build", 3, craft.recipe[1][3])
					end
				end
			end
			if craft.recipe[2] then
				if (type(craft.recipe[2]) == "string") then
					inv:set_stack("build", 2, craft.recipe[2])
				else
					if craft.recipe[2][1] then
						inv:set_stack("build", 4, craft.recipe[2][1])
					end
					if craft.recipe[2][2] then
						inv:set_stack("build", 5, craft.recipe[2][2])
					end
					if craft.recipe[2][3] then
						inv:set_stack("build", 6, craft.recipe[2][3])
					end
				end
			end
			if craft.recipe[3] then
				if (type(craft.recipe[3]) == "string") then
					inv:set_stack("build", 3, craft.recipe[3])
				else
					if craft.recipe[3][1] then
						inv:set_stack("build", 7, craft.recipe[3][1])
					end
					if craft.recipe[3][2] then
						inv:set_stack("build", 8, craft.recipe[3][2])
					end
					if craft.recipe[3][3] then
						inv:set_stack("build", 9, craft.recipe[3][3])
					end
				end
			end
			if craft.recipe[4] then
				if (type(craft.recipe[4]) == "string") then
					inv:set_stack("build", 4, craft.recipe[4])
				end
			end
			if craft.recipe[5] then
				if (type(craft.recipe[5]) == "string") then
					inv:set_stack("build", 5, craft.recipe[5])
				end
			end
			if craft.recipe[6] then
				if (type(craft.recipe[6]) == "string") then
					inv:set_stack("build", 6, craft.recipe[6])
				end
			end
			if craft.recipe[7] then
				if (type(craft.recipe[7]) == "string") then
					inv:set_stack("build", 7, craft.recipe[7])
				end
			end
			if craft.recipe[8] then
				if (type(craft.recipe[8]) == "string") then
					inv:set_stack("build", 8, craft.recipe[8])
				end
			end
			if craft.recipe[9] then
				if (type(craft.recipe[9]) == "string") then
					inv:set_stack("build", 9, craft.recipe[9])
				end
			end
		end
	end
	if meta:get_string("switch")=="youneed" and craft_guide.you_need then
		craft_guide.you_need_list=nil
		craft_guide.you_need_list={}
		local stack_name=stack:get_name()
		-- get the saved list if we have it already, no need to calcalute all again
		if craft_guide.saved_you_need_lists[stack_name.."@|²"..tostring(alternate)]~=nil then
			craft_guide.you_need_list=craft_guide.saved_you_need_lists[stack_name.."@|²"..tostring(alternate)]
			globalcount=tonumber(craft_guide.saved_you_need_lists[stack_name.."@|³"..tostring(alternate)])
			if globalcount==nil or globalcount<1 then
				globalcount=1
			end
			local v=1
			for _item,_ in pairs(craft_guide.you_need_list) do
				inv:set_stack("youneed", v, _item)
				v=v+1
			end
		else
			list[stack_name] = {}
			list[stack_name] = 1
			for j=1,6,1 do	--main iteration loop for resolving recipes into base items
				local finished=1
				local limit=inv:get_size("youneed")
				local k=0
				for name,count in pairs(list) do
					if k>limit then
						break
					end
					k=k+1
					local isbase=0
					if name==nil or name=="" or count==0 or string.sub(name,1,6)=="group:" then
						isbase=1
					elseif j>1 or k>1 then
						for ii=1,999,1 do
							if craft_guide.basic_item_prefixes[ii]==nil or craft_guide.basic_item_prefixes[ii]=="" then  
								break
							elseif string.sub(name,1,string.len(craft_guide.basic_item_prefixes[ii]))==
								string.lower(craft_guide.basic_item_prefixes[ii]) then
								isbase=1
								break
							end
						end
						if isbase==0 then
							for aa=1,999,1 do
								if craft_guide.basic_item_groups[aa]==nil or craft_guide.basic_item_groups[aa]=="" then  
									break
								elseif minetest.get_item_group(name, string.lower(craft_guide.basic_item_groups[aa]))>0 then
									isbase=1
									break
								end
							end
							if isbase==0 then
								for bb=1,999,1 do
									if craft_guide.basic_item_endings[bb]==nil 
										or craft_guide.basic_item_endings[bb]=="" then  	
										break
									elseif string.sub(name,string.len(name)-
										(string.len(craft_guide.basic_item_endings[bb])-1)	)==
										string.lower(craft_guide.basic_item_endings[bb]) then
										isbase=1
										break
									end
								end
								if isbase==0 then
									for cc=1,999,1 do
										if craft_guide.basic_items[cc]==nil or craft_guide.basic_items[cc]=="" then  
											break
										elseif name==string.lower(craft_guide.basic_items[cc]) then
											isbase=1
											break
										end
									end
								end
							end
						end
					end
					crafts = craft_guide.crafts[name]
					if crafts==nil or ((j>1 or k>1) and crafts[1].type~=nil 
						and crafts[1].type~="cooking" and crafts[1].type~="shapeless") 	then
						isbase=1
					end
					if isbase==0 then
						finished=0
						if crafts ~= nil then
							local istest=1
							local bestcraft=1
							local bestvalue=10 --lower is better


--too much tabs needed, starting here left again till this section is over
for craftnumber=1,#crafts+1,1 do
	if craftnumber>49 then
		craftnumber=#crafts+1
	end
	local index=craftnumber
	if j>1 then
		if #crafts==1 and index<=#crafts then 
			bestvalue=0
			istest=0
		elseif index>#crafts or bestvalue==0 then
			index=bestcraft
			bestvalue=0
			istest=0
		end
	else
		bestvalue=0
		index=alternate
		istest=0
	end
	local craft = crafts[index]
	if craft~=nil and craft.type~="fuel" then
		local amount=count
		if istest==0 then
			list[name]=0
			local output_count=ItemStack(craft.output):get_count()
			if output_count~=1 and (j>1 or k>1) then
				if amount/output_count==math.floor(amount/output_count) then
					amount=amount/output_count
				else
					globalcount=globalcount*output_count
					for _name,_amount in pairs(list) do
						if tonumber(amount)>0 then
							list[_name]=tonumber(_amount)*output_count
						end
					end
				end
			end
		end
		if istest==1 then
			list2=list
			list=nil
			list={}
			list=test
		end
		if craft.type == "cooking" then
			if list[craft.recipe]==nil then
				list[(craft.recipe)]={}
				list[(craft.recipe)]=amount
			else
				local add=amount+tonumber(list[(craft.recipe)])
				list[(craft.recipe)]=add
			end
		elseif craft.type ~=nil and craft.type ~= "fuel" and craft.type ~= "shapeless" then
			local input=ItemStack(craft.input):get_name()
			local _count=ItemStack(craft.input):get_count()
			if input~=nil and input~="" then
				if list[input]==nil then
					list[input]={}
					list[input]=amount*_count
				else
					local add=amount*_count+tonumber(list[input])
					list[input]=add
				end
			else
				input=ItemStack(craft.input[1]):get_name()
				_count=ItemStack(craft.input[1]):get_count()
				if input~=nil and input~="" then
					if list[input]==nil then
						list[input]={}
						list[input]=amount*_count
					else
						local add=amount*_count+tonumber(list[input])
						list[input]=add
					end
					input=ItemStack(craft.input[2]):get_name()
					_count=ItemStack(craft.input[2]):get_count()
					if input~=nil and input~="" then
						if list[input]==nil then
						list[input]={}
						list[input]=amount*_count
					else
						local add=amount*_count+tonumber(list[input])
						list[input]=add
					end
				end
			end
		end
	elseif craft.type==nil or craft.type=="shapeless" then
		if craft.recipe[1] then
			if (type(craft.recipe[1]) == "string") then
				if list[craft.recipe[1]]==nil then
					list[(craft.recipe[1])]={}
					list[(craft.recipe[1])]=amount
				else
					local add =amount+tonumber(list[(craft.recipe[1])])
					list[(craft.recipe[1])]=add
				end
			else
				if craft.recipe[1][1] then
					if list[(craft.recipe[1][1])]==nil then
						list[(craft.recipe[1][1])]={}
						list[(craft.recipe[1][1])]=amount
					else
						local add =amount+tonumber(list[(craft.recipe[1][1])])
						list[(craft.recipe[1][1])]=add
					end
				end
				if craft.recipe[1][2] then
					if list[(craft.recipe[1][2])]==nil then
						list[(craft.recipe[1][2])]={}
						list[(craft.recipe[1][2])]=amount
					else
						local add =amount+tonumber(list[(craft.recipe[1][2])])
						list[(craft.recipe[1][2])]=add
					end
				end
				if craft.recipe[1][3] then
					if list[(craft.recipe[1][3])]==nil then
						list[(craft.recipe[1][3])]={}
						list[(craft.recipe[1][3])]=amount
					else
						local add =amount+tonumber(list[(craft.recipe[1][3])])
						list[(craft.recipe[1][3])]=add
					end
				end
			end
		end
		if craft.recipe[2] then
			if (type(craft.recipe[2]) == "string") then
				if list[(craft.recipe[2])]==nil then
					list[(craft.recipe[2])]={}
					list[(craft.recipe[2])]=amount
				else
					local add =amount+tonumber(list[(craft.recipe[2])])
					list[(craft.recipe[2])]=add
				end
			else
				if craft.recipe[2][1] then
					if list[(craft.recipe[2][1])]==nil then
						list[(craft.recipe[2][1])]={}
						list[(craft.recipe[2][1])]=amount
					else
						local add =amount+tonumber(list[(craft.recipe[2][1])])
						list[(craft.recipe[2][1])]=add
					end
				end
				if craft.recipe[2][2] then
					if list[(craft.recipe[2][2])]==nil then
						list[(craft.recipe[2][2])]={}
						list[(craft.recipe[2][2])]=amount
					else
						local add =amount+tonumber(list[(craft.recipe[2][2])])
						list[(craft.recipe[2][2])]=add
					end
				end
				if craft.recipe[2][3] then
					if list[(craft.recipe[2][3])]==nil then
						list[(craft.recipe[2][3])]={}
						list[(craft.recipe[2][3])]=amount
					else
						local add =amount+tonumber(list[(craft.recipe[2][3])])
						list[(craft.recipe[2][3])]=add
					end
				end
			end
		end
		if craft.recipe[3] then
			if (type(craft.recipe[3]) == "string") then
				if list[(craft.recipe[3])]==nil then
					list[(craft.recipe[3])]={}
					list[(craft.recipe[3])]=amount
				else
					local add =amount+tonumber(list[(craft.recipe[3])])
					list[(craft.recipe[3])]=add
				end
			else
				if craft.recipe[3][1] then
					if list[(craft.recipe[3][1])]==nil then
						list[(craft.recipe[3][1])]={}
						list[(craft.recipe[3][1])]=amount
					else
						local add =amount+tonumber(list[(craft.recipe[3][1])])
						list[(craft.recipe[3][1])]=add
					end
				end
				if craft.recipe[3][2] then
					if list[(craft.recipe[3][2])]==nil then
						list[(craft.recipe[3][2])]={}
						list[(craft.recipe[3][2])]=amount
					else
						local add =amount+tonumber(list[(craft.recipe[3][2])])
						list[(craft.recipe[3][2])]=add
					end
				end
				if craft.recipe[3][3] then
					if list[(craft.recipe[3][3])]==nil then
						list[(craft.recipe[3][3])]={}
						list[(craft.recipe[3][3])]=amount
					else
						local add =amount+tonumber(list[(craft.recipe[3][3])])
						list[(craft.recipe[3][3])]=add
					end
				end
			end
		end
		if craft.recipe[4] then
			if (type(craft.recipe[4]) == "string") then
				if list[(craft.recipe[4])]==nil then
					list[(craft.recipe[4])]={}
					list[(craft.recipe[4])]=amount
				else
					local add =amount+tonumber(list[(craft.recipe[4])])
					list[(craft.recipe[4])]=add
				end
			end
		end
		if craft.recipe[5] then
			if (type(craft.recipe[5]) == "string") then
				if list[(craft.recipe[5])]==nil then
					list[(craft.recipe[5])]={}
					list[(craft.recipe[5])]=amount
				else
					local add =amount+tonumber(list[(craft.recipe[5])])
					list[(craft.recipe[5])]=add
				end
			end
		end
		if craft.recipe[6] then
			if (type(craft.recipe[6]) == "string") then
				if list[(craft.recipe[6])]==nil then
					list[(craft.recipe[6])]={}
					list[(craft.recipe[6])]=amount
				else
					local add =amount+tonumber(list[(craft.recipe[6])])
					list[(craft.recipe[6])]=add
				end
			end
		end
		if craft.recipe[7] then
			if (type(craft.recipe[7]) == "string") then
				if list[(craft.recipe[7])]==nil then
					list[(craft.recipe[7])]={}
					list[(craft.recipe[7])]=amount
				else
					local add =amount+tonumber(list[(craft.recipe[7])])
					list[(craft.recipe[7])]=add
				end
			end
		end
		if craft.recipe[8] then
			if (type(craft.recipe[8]) == "string") then
				if list[(craft.recipe[8])]==nil then
					list[(craft.recipe[8])]={}
					list[(craft.recipe[8])]=amount
				else
					local add =amount+tonumber(list[(craft.recipe[8])])
					list[(craft.recipe[8])]=add
				end
			end
		end
		if craft.recipe[9] then
			if (type(craft.recipe[9]) == "string") then
				if list[(craft.recipe[9])]==nil then
					list[(craft.recipe[9])]={}
					list[(craft.recipe[9])]=amount
				else
					local add =amount+tonumber(list[(craft.recipe[9])])
					list[(craft.recipe[9])]=add
				end
			end
		end
	end
	if istest==1 then
		test=list
		list=nil
		list={}
		list=list2
	end
end
	
if istest==1 then
	local value=0
	local h=0
	for name,testcount in pairs(test) do
		h=h+1
		if h>888 then
			break
		end
		if testcount>0 then
			if name.def==nil or (craft_guide.crafts[name]==nil 
				and string.sub(name,1,8)=="technic:")
				then
				bestvalue=10
				h=999
			else
				local testcrafts = craft_guide.crafts[name]
				local testcraft=""
				if testcrafts~=nil then
					testcraft=testcrafts[1]
				end
				local isbase=0

	
				if name==nil or name==""
					or string.sub(name,1,6)=="group:" 
					or testcrafts==nil or testcraft==nil
					or (testcraft.type~=nil and testcraft.type~="shapeless")
					then
					isbase=1
				else
					for ii=1,999,1 do
						if craft_guide.basic_item_prefixes[ii]==nil or craft_guide.basic_item_prefixes[ii]=="" then  
							break
						elseif string.sub(name,1,string.len(craft_guide.basic_item_prefixes[ii]))==
							string.lower(craft_guide.basic_item_prefixes[ii]) then
							isbase=1
							break
						end
					end
					if isbase==0 then
						for aa=1,999,1 do
							if craft_guide.basic_item_groups[aa]==nil or craft_guide.basic_item_groups[aa]=="" then  
								break
							elseif minetest.get_item_group(name, string.lower(craft_guide.basic_item_groups[aa]))>0 then
								isbase=1
								break
							end
						end
						if isbase==0 then
							for bb=1,999,1 do
								if craft_guide.basic_item_endings[bb]==nil or craft_guide.basic_item_endings[bb]=="" then  
									break
								elseif string.sub(name,string.len(name)-(string.len(craft_guide.basic_item_endings[bb])-1))==
									string.lower(craft_guide.basic_item_endings[bb]) then
									isbase=1
									break
								end
							end
							if isbase==0 then
								for cc=1,999,1 do
									if craft_guide.basic_items[cc]==nil or craft_guide.basic_items[cc]=="" then  
										break
									elseif name==string.lower(craft_guide.basic_items[cc]) then
										isbase=1
										break
									end
								end
							end
						end
					end
				end


			if isbase==0 then
				value=value+1
--				if string.find(name,"slab")~=nil
--					or string.find(name,"panel")~=nil
--					or string.find(name,"microblock")~=nil
--					or string.find(name,"stair")~=nil
--					then
--					value=value+5
--				end
			end
		end
	end
end


--starting with correct tabs here again:
									if value<bestvalue then
										bestcraft=index
										bestvalue=value
									end
								else
									craftnumber=999
									break
								end
							end
						end
					end
				end
				if finished==1 then
					break
				end
			end
		end
		local jj=1
		local duplicate=0
		for name,amount in pairs(list) do
			local count=tonumber(amount)
			if name~=nil and count>0 and string.lower(name)~=string.upper(name) then
				local lower=string.lower(name)
				if craft_guide.you_need_list[lower]~=nil and craft_guide.you_need_list[lower]>0 then
					craft_guide.you_need_list[lower]=count+craft_guide.you_need_list[lower]
				else
					inv:add_item("youneed", lower)
					if inv:get_stack("youneed",jj)==nil or inv:get_stack("youneed",jj):get_name()=="" then
						for jjj=1,jj,1 do
							if inv:get_stack("youneed",jjj):get_count()>1 then
								local alias=string.lower(inv:get_stack("youneed",jjj):get_name())
								if craft_guide.you_need_list[alias]==nil then
									craft_guide.you_need_list[alias]={}
									craft_guide.you_need_list[alias]=count
									inv:set_stack("youneed",jjj,alias)
								else							
									craft_guide.you_need_list[alias]=craft_guide.you_need_list[alias]+count
									inv:set_stack("youneed",jjj,alias)
								end
							end
						end
						inv:set_stack("youneed",jj,ItemStack(nil))
						duplicate=1
						list[lower]=0

					elseif string.lower(inv:get_stack("youneed",jj):get_name())~=lower then
						local alias=string.lower(inv:get_stack("youneed",jj):get_name())
						if craft_guide.you_need_list[alias]~=nil then
							craft_guide.you_need_list[alias]=craft_guide.you_need_list[alias]+count
						else
							if list[alias]==nil then
								craft_guide.you_need_list[alias]={}
								craft_guide.you_need_list[alias]=count
								inv:set_stack("youneed",jj,alias)
							else
								list[alias]=list[alias]+count
							end
						end
						list[lower]=0
					else
						craft_guide.you_need_list[lower]={}
						craft_guide.you_need_list[lower]=count
					end
					if duplicate==0 then
						jj=jj+1
					else
						duplicate=0
					end
					if jj>inv:get_size("youneed") then
						break
					end
				end
			end
			craft_guide.saved_you_need_lists[stack_name.."@|²"..tostring(alternate)]={}
			craft_guide.saved_you_need_lists[stack_name.."@|²"..tostring(alternate)]=craft_guide.you_need_list
			craft_guide.saved_you_need_lists[stack_name.."@|³"..tostring(alternate)]={}
			craft_guide.saved_you_need_lists[stack_name.."@|³"..tostring(alternate)]=tostring(globalcount)
		end
	end
	meta:set_string("globalcount",tostring(globalcount))
	meta:set_string("formspec",craft_guide.get_craft_guide_formspec(meta))
end

-- create_inventory
craft_guide.create_inventory = function(inv, search)
	local craft_guide_list = {}
	for name,def in pairs(minetest.registered_items) do
		-- local craft_recipe = minetest.get_craft_recipe(name);
		-- if craft_recipe.items ~= nil then
		local craft = craft_guide.crafts[name];
		if (not def.groups.not_in_craft_guide or def.groups.not_in_craft_guide == 0)
			and (craft ~= nil or (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0))
			--and (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0)
			and def.description and def.description ~= "" then
			if search and search~="" then
				--search used to display groups of items
				--if you enter something in search field it displays items without crafting recipes too
				search=string.lower(search)
				if string.sub(search,1,6)=="group:" then
					local groups=string.sub(search,7)
					local hasgroup=0
					for group in string.gmatch(groups,"([^,]+)") do
						if minetest.get_item_group(name, group)>0 then
							hasgroup=1
						else
							hasgroup=0
							break
						end
					end
					if hasgroup==1 then
						table.insert(craft_guide_list, name)
					end
				else
					search=string.lower(search)
					local test1=0
					local test2=0
					local test3=0
					test1,test2=string.find(string.lower(def.name.."           "), search)					
					test2,test3=string.find(string.lower(def.description.."           "), search)					
					if (test1~=nil and test1>0) or (test2~=nil and test2>0) or search=="*" then
						table.insert(craft_guide_list, name)
					end
				end
			else
				if craft~=nil and ((craft[1]).type~="fuel" or craft_guide.show_all_fuel_crafts) then
					table.insert(craft_guide_list, name)
				end
			end
		end
	end
	table.sort(craft_guide_list)
	for i=0,inv:get_size("main"),1 do
		inv:set_stack("main", i, nil)
	end
	inv:set_size("main", #craft_guide_list)
	for _,itemstring in ipairs(craft_guide_list) do
		inv:add_item("main", ItemStack(itemstring))
	end
end


-- add fuel recipes and recipes from technic machines to craft list
craft_guide.add_additional_crafts = function()
	if craft_guide.other_crafting_types then
		if minetest.get_modpath("technic") then
			local oldversion=false
			local recipelist={}
			if technic.recipes==nil or technic.recipes["grinding"]==nil and technic.grinder_recipes~=nil then
				oldversion=true
				recipelist=technic.grinder_recipes
				for t,recipe in pairs(recipelist) do
					recipe.type="Grinder"
					local name=ItemStack(recipe.output):get_name()
					if name~=nil and name~="" then
						if craft_guide.crafts[name]==nil then
							craft_guide.crafts[name] = {}
						end
						recipe.time=recipe.time or 3
						table.insert(craft_guide.crafts[name],recipe)
					end
				end

			else
				recipelist=technic.recipes["grinding"].recipes
				for t,recipe in pairs(recipelist) do
					recipe.type="Grinder"
					local name=ItemStack(recipe.output):get_name()
					if name~=nil and name~="" and (not craft_guide.remove_cluttering_crafts 
						or (string.find(name,"technic:uranium._")==nil
						and string.find(name,"technic:uranium.._")==nil)) then
						if craft_guide.crafts[name]==nil then
							craft_guide.crafts[name] = {}
						end
						local idx=1
						for _name, _count in pairs(recipe.input) do
							recipe.input[idx]=_name.." ".._count
							break
						end
						recipe.time=recipe.time or 3
						table.insert(craft_guide.crafts[name],recipe)
					end
				end

			end

			if oldversion then
				for t,recipe in pairs(technic.compressor_recipes) do
					recipe.type="Compressor"
					local name=ItemStack(recipe.dst_name):get_name()
					if name~=nil and name~="" then
						if craft_guide.crafts[name]==nil then
							craft_guide.crafts[name] = {}
						end
						recipe.input=t.." "..tostring(recipe.src_count)
						recipe.output=recipe.dst_name.." "..tostring(recipe.dst_count)
						recipe.time=recipe.time or 4
						table.insert(craft_guide.crafts[name],recipe)
					end
				end
			else
				for t,recipe in pairs(technic.recipes["compressing"].recipes) do
					recipe.type="Compressor"
					local name=ItemStack(recipe.output):get_name()
					if name~=nil and name~="" then
						if craft_guide.crafts[name]==nil then
							craft_guide.crafts[name] = {}
						end
						local idx=1
						for _name, _count in pairs(recipe.input) do
							recipe.input[idx]=_name.." ".._count
							break
						end
						recipe.time=recipe.time or 4
						table.insert(craft_guide.crafts[name],recipe)
					end
				end

			end
			if oldversion then
				for t,recipe in pairs(technic.extractor_recipes) do
					recipe.type="Extractor"
					local name=ItemStack(recipe.dst_name):get_name()
					if name~=nil and name~="" then
						if craft_guide.crafts[name]==nil then
							craft_guide.crafts[name] = {}
						end
						recipe.input=t.." "..tostring(recipe.src_count)
						recipe.output=recipe.dst_name.." "..tostring(recipe.dst_count)
						recipe.time=recipe.time or 4
						table.insert(craft_guide.crafts[name],recipe)
					end
				end
			else
				for t,recipe in pairs(technic.recipes["extracting"].recipes) do
					recipe.type="Extractor"
					local name=ItemStack(recipe.output):get_name()
					if name~=nil and name~="" then
						if craft_guide.crafts[name]==nil then
							craft_guide.crafts[name] = {}
						end
						local idx=1
						for _name, _count in pairs(recipe.input) do
							recipe.input[idx]=_name.." ".._count
							break
						end
						recipe.time=recipe.time or 4
						table.insert(craft_guide.crafts[name],recipe)
					end
				end

			end
			if oldversion then
				recipelist=technic.alloy_recipes
				for t,recipe in pairs(recipelist) do
					recipe.type="Alloy Furnace"
					local name=ItemStack(recipe.output):get_name()
					if name~=nil and name~="" then
						if craft_guide.crafts[name]==nil then
							craft_guide.crafts[name] = {}
						end
						recipe.time=recipe.time or 6
						table.insert(craft_guide.crafts[name],recipe)
					end
				end
			else
				recipelist=technic.recipes["alloy"].recipes
				for t,recipe in pairs(recipelist) do
					local rec={}
					rec.type="Alloy Furnace"
					local name=ItemStack(recipe.output):get_name()
					if name~=nil and name~="" then
						if craft_guide.crafts[name]==nil then
							craft_guide.crafts[name] = {}
						end
						local idx=1
						rec.output=recipe.output
						rec.time=recipe.time or 6
						rec.input={}
						for _name, _count in pairs(recipe.input) do
							rec.input[idx]=_name.." ".._count
							idx=idx+1
							if idx>2 then
							break
							end
						end
						table.insert(craft_guide.crafts[name],rec)
					end
				end
			end
			if not oldversion then
				for t,recipe in pairs(technic.recipes["separating"].recipes) do
					local rec={}
					local rec2={}
					
					rec.type="Centrifuge"
					rec2.type="Centrifuge"
					local name=ItemStack(recipe.output[1]):get_name()
					local name2=ItemStack(recipe.output[2]):get_name()
					local count=ItemStack(recipe.output[1]):get_count()
					local count2=ItemStack(recipe.output[2]):get_count()
					if name~=nil and name~="" and (not craft_guide.remove_cluttering_crafts
						or (string.find(name,"technic:uranium._")==nil
						and string.find(name,"technic:uranium.._")==nil)) then
						if craft_guide.crafts[name]==nil then
							craft_guide.crafts[name] = {}
						end
						local idx=1
						rec.input={}
						rec2.input={}
						for _name, _count in pairs(recipe.input) do
							rec.input[idx]=_name.." ".._count
							rec2.input[idx]=_name.." ".._count
							break
						end
						rec.time=recipe.time or 10
						rec2.time=recipe.time or 10
						rec.output2=name2.." "..tostring(count2)
						rec.output=name.." "..tostring(count)
						table.insert(craft_guide.crafts[name],rec)
						if name2~=nil and name2~="" and (not craft_guide.remove_cluttering_crafts
							or (string.find(name2,"technic:uranium._")==nil
							and string.find(name2,"technic:uranium.._")==nil)) then
							if craft_guide.crafts[name2]==nil then
									craft_guide.crafts[name2] = {}
							end
							rec2.output=name2.." "..tostring(count2)
							rec2.output2=name.." "..tostring(count)
							table.insert(craft_guide.crafts[name2],rec2)
						end
					end
				end
				
			end

		end
	end

	craft_guide.other_crafting_types = false
	if craft_guide.fuel_to_add then
		--add crafts with type "fuel"
		for name,def in pairs(minetest.registered_items) do
			if (not def.groups.not_in_craft_guide or def.groups.not_in_craft_guide == 0) then
				if craft_guide.fuel[name]~=nil then
					if craft_guide.crafts[name]==nil then
						craft_guide.crafts[name] = {}
					end
					local fuels=craft_guide.fuel[name]
					local fuel=fuels[1]
					table.insert(craft_guide.crafts[name],fuel)
				else
					local best=0
					local bestgroup=""
					for group,_ in pairs(def.groups) do
						if craft_guide.fuel["group:"..group]~=nil then
							local fuels=craft_guide.fuel["group:"..group]
							local fuel=fuels[1]
							if fuel.burntime>best then
								best=fuel.burntime
								bestgroup=group
							end
						end
					end
					if bestgroup~="" then
						if craft_guide.crafts[name]==nil then
							craft_guide.crafts[name] = {}
						end
						local fuels=craft_guide.fuel["group:"..bestgroup]
						local fuel=fuels[1]
						table.insert(craft_guide.crafts[name],fuel)
					end
				end
			end
		end	
	end

	craft_guide.fuel_to_add=false
	craft_guide.fuel=nil
	craft_guide.fuel={}
	-- all aliases should share the same crafting recipes
	if craft_guide.add_things then
		for i=1,9999,2 do
			local alias=craft_guide.alias[i]
			local convert_to=craft_guide.alias[i+1]
			if alias~=nil and convert_to~=nil and (craft_guide.crafts[convert_to]~=nil or craft_guide.crafts[alias]~=nil) then
				if craft_guide.crafts[convert_to]==nil and craft_guide.crafts[alias]~=nil then
					craft_guide.crafts[convert_to]={}
				elseif craft_guide.crafts[alias]==nil and craft_guide.crafts[convert_to]~=nil then
					craft_guide.crafts[alias]={}
				end
				for ii=1,9999,1 do
					local craft=(craft_guide.crafts[alias])[ii]
					if craft==nil then
						break
					else
						table.insert(craft_guide.crafts[convert_to],craft)
					end
				end
			craft_guide.crafts[alias]={}
				for ii=1,9999,1 do
					local craft=(craft_guide.crafts[convert_to])[ii]
					if craft==nil then
						break
					else
						table.insert(craft_guide.crafts[alias],craft)
					end
				end

			end
		end
	end
	craft_guide.add_things=false
end


-- allow_metadata_inventory_move
craft_guide.allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
	local meta = minetest.env:get_meta(pos)
	if meta:get_string("locked")=="1" then
		craft_guide.save_meta(meta)
	end

	local inv = meta:get_inventory()
	if to_list == "bin" and from_list == "output" then
		inv:set_stack(from_list,from_index,nil)
		craft_guide.update_recipe(meta, player, inv:get_stack(from_list, from_index))
	end
	if to_list == "bin" and from_list == "bookmark" then
		inv:set_stack(from_list,from_index,nil)
		inv:set_stack("add",1,nil)--clear this because bookmarks aren't full anymore
	end
	if to_list == "bookmark" and not inv:contains_item("bookmark",inv:get_stack(from_list, from_index):get_name()) then
		inv:set_stack(to_list, to_index, inv:get_stack(from_list, from_index):get_name())
		if not inv:contains_item("bookmark",ItemStack(nil)) then
			inv:set_stack("add", 1, inv:get_stack("bookmark", tonumber(meta:get_string("addindex"))):get_name())
		end
	end
	if to_list == "add" and not inv:contains_item("bookmark",inv:get_stack(from_list, from_index):get_name()) then
		local index=tonumber(meta:get_string("addindex"))
		local stack=inv:get_stack("bookmark",index)
		local status=0
		if stack~=nil and stack:get_name()~=nil and stack:get_name()~="" then
			for i=1,inv:get_size("bookmark"),1 do
				stack=inv:get_stack("bookmark",i)
				if stack~=nil and stack:get_name()~=nil and stack:get_name()~="" then
				else
					if status==0 then
						inv:set_stack("bookmark", i, inv:get_stack(from_list, from_index):get_name())
						meta:set_string("addindex",tostring(i))
						status=1
					elseif status==1 then
						status=2
					end
				end
			end
			if status==1 then --bookmarks are full now
				inv:set_stack("add", to_index, inv:get_stack(from_list, from_index):get_name())
			elseif status==2 then --bookmarks has still empty slots after adding this stack
				inv:set_stack("add", to_index, nil)
			elseif status==0 then --bookmarks were already full, replace last added item
				inv:set_stack("bookmark", index, inv:get_stack(from_list, from_index):get_name())
				inv:set_stack("add", to_index, inv:get_stack(from_list, from_index):get_name())
			end
		else
			inv:set_stack("bookmark", index, inv:get_stack(from_list, from_index):get_name())
			inv:set_stack("add", to_index, nil)
		end
	end
	if to_list == "output" or from_list == "output" then
		if from_list ~= "output" and to_list == "output" then
			local name=inv:get_stack(from_list, from_index)
			if name~=nil then
				name=name:get_name()
			end
			if name~=nil then
				meta:set_string("out",name)
				inv:set_stack(to_list, to_index, nil)
			end
		end
		if from_list == "output" and (to_list == "bin" or to_list=="add" ) then
			meta:set_string("out","")
		end
		craft_guide.update_recipe(meta, player, inv:get_stack(from_list, from_index))
	end
	if from_list == "bookmark" and to_list == "bookmark"  then
		return count
	end
	return 0
end


-- allow_metadata_inventory_put
craft_guide.allow_metadata_inventory_put = function(pos, listname, index, stack, player)
	return 0
end


-- allow_metadata_inventory_take
craft_guide.allow_metadata_inventory_take = function(pos, listname, index, stack, player)
	return 0
end

craft_guide.save_meta = function (meta)
	meta:set_string("saved_search2",meta:get_string("saved_search"))
	meta:set_string("saved_page2",meta:get_string("saved_page"))
	meta:set_string("saved_pages2",meta:get_string("saved_pages"))
	meta:set_string("switch2",meta:get_string("switch"))
	meta:set_string("poslist2",meta:get_string("poslist"))
	meta:set_string("globalcount2",meta:get_string("globalcount"))
	meta:set_string("time2",meta:get_string("time"))
	meta:set_string("method2",meta:get_string("method"))
	meta:set_string("out2",meta:get_string("out"))
	meta:set_string("addindex2",meta:get_string("addindex"))
	meta:set_string("search2",meta:get_string("search"))
	local inv=meta:get_inventory()
	inv:set_size("main2", inv:get_size("main"))
	inv:set_size("output2", 1)
	inv:set_size("additional2", 1)
	inv:set_size("build2", 3*3)
	inv:set_size("cook2", 2*1)
	inv:set_size("fuel2", 1)
	inv:set_size("machine2", 1)
	inv:set_size("bookmark2", 6*3)
	inv:set_size("youneed2", 6*15)
	inv:set_size("bin2", 1)
	inv:set_size("add2", 1)
	for i=0,inv:get_size("main2"),1 do
		inv:set_stack("main2", i, inv:get_stack("main",i))
	end
	for i=0,inv:get_size("build2"),1 do
		inv:set_stack("build2", i, inv:get_stack("build",i))
	end
	for i=0,inv:get_size("bookmark2"),1 do
		inv:set_stack("bookmark2", i, inv:get_stack("bookmark",i))
	end
	for i=0,inv:get_size("youneed2"),1 do
		inv:set_stack("youneed2", i, inv:get_stack("youneed",i))
	end
	inv:set_stack("cook2", 1, inv:get_stack("cook",1))
	inv:set_stack("cook2", 2, inv:get_stack("cook",2))
	inv:set_stack("output2", 1, inv:get_stack("output",1))
	inv:set_stack("additional2", 1, inv:get_stack("additional",1))
	inv:set_stack("fuel2", 1, inv:get_stack("fuel",1))
	inv:set_stack("bin2", 1, inv:get_stack("bin",1))
	inv:set_stack("machine2", 1, inv:get_stack("machine",1))
	inv:set_stack("add2", 1, inv:get_stack("add",1))
	meta:set_string("locked","2")
	meta:set_string("formspec2",meta:get_string("saved_formspec"))

end

craft_guide.restore_meta = function (meta)
	meta:set_string("saved_search",meta:get_string("saved_search2"))
	meta:set_string("saved_page",meta:get_string("saved_page2"))
	meta:set_string("saved_pages",meta:get_string("saved_pages2"))
	meta:set_string("switch",meta:get_string("switch2"))
	meta:set_string("poslist",meta:get_string("poslist2"))
	meta:set_string("globalcount",meta:get_string("globalcount2"))
	meta:set_string("time",meta:get_string("time2"))
	meta:set_string("method",meta:get_string("method2"))
	meta:set_string("out",meta:get_string("out2"))
	meta:set_string("addindex",meta:get_string("addindex2"))
	meta:set_string("search",meta:get_string("search2"))
	local inv=meta:get_inventory()
	inv:set_size("main",inv:get_size("main2"))
	for i=0,inv:get_size("main"),1 do
		inv:set_stack("main", i, inv:get_stack("main2",i))
	end
	for i=0,inv:get_size("build"),1 do
		inv:set_stack("build", i, inv:get_stack("build2",i))
	end
	for i=0,inv:get_size("bookmark"),1 do
		inv:set_stack("bookmark", i, inv:get_stack("bookmark2",i))
	end
	for i=0,inv:get_size("youneed"),1 do
		inv:set_stack("youneed", i, inv:get_stack("youneed2",i))
	end
	inv:set_stack("cook", 1, inv:get_stack("cook2",1))
	inv:set_stack("cook", 2, inv:get_stack("cook2",2))
	inv:set_stack("output", 1, inv:get_stack("output2",1))
	inv:set_stack("additional", 1, inv:get_stack("additional2",1))
	inv:set_stack("fuel", 1, inv:get_stack("fuel2",1))
	inv:set_stack("bin", 1, inv:get_stack("bin2",1))
	inv:set_stack("machine", 1, inv:get_stack("machine2",1))
	inv:set_stack("add", 1, inv:get_stack("add2",1))
	meta:set_string("isowner","0")
	meta:set_string("locked","1")
local formspec=	meta:get_string("formspec2")
	meta:set_string("saved_formspec",formspec)
	formspec=formspec.."label[0.88,9.2;Locked]"
		.."tooltip[close_mm;   Owner: "..meta:get_string("owner").."]"
	meta:set_string("formspec",formspec)

end
