minetest.register_tool("aliveai:book", {
	description = "Ai Book",
	range=15,
	inventory_image = "aliveai_book.png",
	on_use=function(itemstack, user, pointed_thing)
		local pos=user:get_pos()
		local name=user:get_player_name()
		local pos2=pointed_thing.under
		local item=itemstack:to_table()
		local save
		local meta=minetest.deserialize(item.metadata) or {bots={},selected="",pages=0,selected_num=0,user=name,description="Ai Book by ".. name}

		if meta.user==name then
			local bots={}
			for i, b in ipairs(meta.bots) do
				bots[b]=1
			end
			if pointed_thing.type=="node" and aliveai.group(pointed_thing.under,"aliveai")>0 and not bots[minetest.get_node(pointed_thing.under).name] then
				bots[minetest.get_node(pointed_thing.under).name]=1
				if meta.selected=="" then
					meta.selected=minetest.get_node(pointed_thing.under).name
				end
				save=true
			elseif pointed_thing.type=="object" and aliveai.is_bot(pointed_thing.ref) and not bots[pointed_thing.ref:get_luaentity().name] then
				bots[pointed_thing.ref:get_luaentity().name]=1
				meta.selected=pointed_thing.ref:get_luaentity().name
				save=true
			else
				for _, ob in ipairs(minetest.get_objects_inside_radius(pos,5)) do
					if aliveai.is_bot(ob) and not bots[ob:get_luaentity().name] and aliveai.visiable(pos,ob) then
						bots[ob:get_luaentity().name]=1
						meta.selected=ob:get_luaentity().name
						save=true
					end
				end
			end
			if save then
				local sbots={}
				local num=0
				for b, n in pairs(bots) do
					num=num+1
					table.insert(sbots,b)
					if meta.selected_num==0 and b==meta.selected then
						meta.selected_num=num
					end
					meta.pages=num
				end
				meta.bots=sbots
				item.meta={description="Ai Book by ".. name}
				minetest.chat_send_player(name, "Book: New content added")

				if aliveai.grant_invisiable==true and not meta.finished and meta.pages>=aliveai.loaded_objects then
					local p=minetest.get_player_privs(name)
					p.aliveai_invisibility=true
					minetest.set_player_privs(name, p)
					meta.finished=1
					minetest.chat_send_player(name, "Book: You have been granted aliveai_invisibility")
					minetest.chat_send_player(name, "Book: Ai's will not detect you when you are sneaking")
				end

				item.metadata=minetest.serialize(meta)
				itemstack:replace(item)
			end
		end
		aliveai.view_book(user,meta)
		return itemstack
	end,
})

aliveai.view_book=function(user,meta)
	table.sort(meta.bots)
	local list=""
	local c=""
	local name=user:get_player_name()
	local a=aliveai.registered_bots[meta.selected]
	for i, bot in ipairs(meta.bots) do
		list=list .. c .. bot
		c=","
	end

	local gui="size[10,8]"
	.."background[-0.2,-0.2;10.4,8.6;gui_formbg.png]"
	.. "label[8,0;Page: " .. meta.selected_num.. "/" .. meta.pages .. " (" .. aliveai.loaded_objects ..")]"
	.."dropdown[0,-0.1;3,1;list;" .. list.. ";" .. meta.selected_num .."]"
	.."button[3,-0.2;1,1;bac;<]"
	.."button[4,-0.2;1,1;fro;>]"

	if a then
		local light="light"
		local flying="true"
		local drops="none"
		local aggressive="false"
		if a.floating==0 then
			flying="false"
		end
		if a.attacking==1 then
			aggressive="true"
		end
		if a.light<0 then
			light="darknes"
		elseif a.light==0 then
			light="light and darknes"
		end
		if type(a.start_with_items)=="table" then
			drops=""
			local rit
			for it, c in pairs(a.start_with_items) do
				rit=it
				if minetest.registered_items[it] then
					rit=minetest.registered_items[it].description
				end
				drops=drops .. rit .." " .. c ..", "
			end
		end
		gui=gui
		.. "label[0,0.5;"
		.."Name: " .. a.name .."\n"
		.."Type: " .. a.type .."\n"
		.."Team: " .. a.team .."\n"
		.."Health: " .. a.hp .."\n"
		.."Damage: " .. a.dmg .."\n"
		.."Durability: " .. a.mindamage .."\n"
		.."Drops: " .. drops .."\n"
		.."Flying: " .. flying .."\n"
		.."Aggressive: " .. aggressive .."\n"
		.."Thrive in " .. light .."\n\n"
		.. a.description
		.."]"
		.."item_image[5.5,0.5;5,5;" .. a.item .. "]"
	else
		gui=gui .. "label[0,0.5;\nEmpty Ai Book\n\nPunch one or use the book near AI to add.\nBlocks too.]"
	end
	minetest.after(0, function(gui)
		return minetest.show_formspec(name, "aliveai.book",gui)
	end, gui)
end


aliveai.register_buildings_spawner=function(name,def)
	aliveai.buildings_spawners[minetest.get_current_modname() .. "." .. name]={
		name=name,
		mod=minetest.get_current_modname(),
		on_use=def.on_use,
		on_place=def.on_place
	}
end

minetest.register_tool("aliveai:buildings_spawner", {
	description = "Buildings spawner",
	range=15,
	inventory_image = "aliveai_buildings_spawner.png",
	on_use=function(itemstack, user, pointed_thing)
		aliveai.show_buildings_spawner(itemstack, user, pointed_thing)
		return itemstack
	end,
	on_place=function(itemstack, user, pointed_thing)
		aliveai.show_buildings_spawner(itemstack, user, pointed_thing,true)
		return itemstack
	end,
})

aliveai.show_buildings_spawner=function(itemstack, user, pointed_thing,place)
		if not user or type(user)~="userdata" then return end
		local name=user:get_player_name()
		if minetest.check_player_privs(name, {aliveai_buildings_spawning=true})==false then
			if type(itemstack)=="userdata" then
				itemstack:replace(nil)
			end
			minetest.chat_send_player(name,"You are unallowed to use this tool")
			return itemstack
		end
		local use=":on_use"
		if place then
			use=":on_place"
		end
		local gui="size[10,8]"
		local x,y=0,0
		local l=0
		for i, v in pairs(aliveai.buildings_spawners) do
			if (not place and v.on_use) or (place and v.on_place) then
				l=string.len(v.name)
				if l<5 then
					l=1
				elseif l<15 then
					l=2
				else
					l=3	
				end
				gui=gui .. "tooltip[" .. v.mod .."." .. v.name .. use ..";" .. v.name .."]"
				.. "button[" .. x .."," .. y .. ";" .. l ..",1;" .. v.mod .."." .. v.name .. use ..";" .. v.name .."]"
				x=x+l
				if x>10 then
					x=0
					y=y+1
				end

			end
		end
		aliveai.terminal_users[user:get_player_name()]={itemstack=itemstack,user=user,pointed_thing=pointed_thing}
		minetest.after(0, function(gui)
			return minetest.show_formspec(name, "aliveai.buildings_spawner",gui)
		end, gui)
end

minetest.register_on_player_receive_fields(function(player, form, pressed)
	if form=="aliveai.book" then
		if pressed.quit then
			return
		end
		local item=player:get_wielded_item():to_table()
		local meta=minetest.deserialize(item.metadata) or {bots={},selected=""}
		if not meta.pages or meta.pages==0 then return end
		table.sort(meta.bots)
		if pressed.fro then
			meta.selected_num=meta.selected_num+1
			if meta.selected_num>meta.pages then
				meta.selected_num=1
			end
			meta.selected=meta.bots[meta.selected_num]
		elseif pressed.bac then
			meta.selected_num=meta.selected_num-1
			if meta.selected_num<1 then
				meta.selected_num=meta.pages
			end
			meta.selected=meta.bots[meta.selected_num]
		elseif pressed.list then
			meta.selected=pressed.list
			for i, b in ipairs(meta.bots) do
				if b==meta.selected then
					meta.selected_num=i
					break
				end
			end
		end
		item.metadata=minetest.serialize(meta)
		player:get_inventory():set_stack("main", player:get_wield_index(),item)
		aliveai.view_book(player,meta)
	elseif form=="aliveai.buildings_spawner" then
		local name=player:get_player_name()
		if pressed.quit or not aliveai.terminal_users[name] then
			aliveai.terminal_users[name]=nil
			return
		end
		local na
		local s
		for name, v in pairs(pressed) do
			na=name
			break
		end
		s=na.split(na,":")
		if s and s[2] and aliveai.buildings_spawners[s[1]] then
			local a=aliveai.terminal_users[name]
			aliveai.buildings_spawners[s[1]][s[2]](a.itemstack,a.user,a.pointed_thing)
		end
	end
end)



aliveai.crafttools=function(self,t)
	if self.crafting~=1 or math.random(1,10)~=1 then return end
	if type(self.tools)=="table" then return end
	for name, s in pairs(aliveai.tools_handler) do
		if s.try_to_craft and s.tools and not self.creative==1 then
			for i, name2 in pairs(s.tools) do
				if not self.inv[name ..":" ..name2] then
					aliveai.crafting(self,name ..":" ..name2)
				end
			end
		end
	end
	return self
end

aliveai.tool_handler=function(self,t)
	if self.using_tool then return end
	self.using_tool=true
	if not minetest.registered_tools[t] then return end
	local ts=t.split(t,":")
	local tool=aliveai.tools_handler[ts[1]]
	if not tool or not tool.use then return end
	aliveai.showstatus(self,"tool handler")
	if tool.tool_group and minetest.get_item_group(t, tool.tool_group)==0 and minetest.get_item_group(t, tool.tool_group)==0 then
		return
	end
	if tool.tools then
		local nm=true
		for i, name in pairs(tool.tools) do
			if ts[2]==name then nm=false break end
		end
		if nm then return end
	end
	if tool.amo and self.inv[tool.amo] then
		if tool.amo_index and tool.tool_index then
			if tool.amo_index<=tool.tool_index then
				self.tools={tool.amo,t}
			else
				self.tools={t,tool.amo}
			end
		elseif tool.amo_index and tool.amo_index>1 then
			self.tools={tool.amo,t}
		elseif tool.tool_index and tool.tool_index>1 then
			self.tools={t,tool.amo}
		else
			self.tools={tool.amo,t}
		end
	elseif tool.amo_group then
		for name, s in pairs(self.inv) do
			if minetest.get_item_group(name, tool.amo_group)>0 
			or minetest.get_item_group(name, tool.amo_group)>0 then
				if tool.amo_index and tool.tool_index then
					if tool.amo_index<=tool.tool_index then
					self.tools={name,t}
					else
						self.tools={t,name}
					end
				elseif tool.amo_index and tool.amo_index>1 then
					self.tools={name,t}
				elseif tool.tool_index and tool.tool_index>1 then
					self.tools={t,name}
				else
					self.tools={name,t}
				end
			end
		end
	else
		return self
	end
	self.tool_index= tool.tool_index or self.self.tool_index
	self.tool_reuse= tool.tool_reuse or self.tool_reuse
	self.tool_near= tool.tool_near or self.tool_near
	self.tool_see= tool.tool_see or self.tool_see
	self.tool_chance= tool.tool_chance or self.tool_chance
end

aliveai.give_to_bot=function(self,clicker)
	local stack=clicker:get_wielded_item()
	if stack:get_name()=="" or stack:get_name()=="aliveai:team_gift" or stack:get_name()=="aliveai_minecontroller:controller" then
		aliveai.on_spoken_to(self,self.botname,clicker:get_player_name(),"come")
		return self
	end

	if stack:get_name()=="aliveai:hypnotics" then
		local inv=clicker:get_inventory()
		local i=clicker:get_wield_index()
		stack:take_item(1)
		inv:set_stack("main", i,stack)
		if self.hp_max<101 and self.type=="npc" then
			aliveai.sleep(self,2)
		else
			aliveai.punch(self,self.object,20)
		end
		return self
	end

	if stack:get_name()=="aliveai:relive" then
		local inv=clicker:get_inventory()
		local i=clicker:get_wield_index()
		stack:take_item(1)
		inv:set_stack("main", i,stack)

		if self.dying or self.dead then
			aliveai.dying(self,3)
		elseif self.hp_max<101 and self.drop_dead_body==1 then
			self.hp=-10
			aliveai.dying(self,1)
		else
			aliveai.punch(self,self.object,20)
		end
		return self
	end

	if self.dead then return end
	self.mood=self.mood+1
	local inv=clicker:get_inventory()
	local i=clicker:get_wield_index()
	if self.hp<self.hp_max and minetest.get_item_group(stack:get_name(),"aliveai_eatable")>0 then
		aliveai.known(self,clicker,"member")
		self.mood=self.mood+2
		aliveai.sayrnd(self,"thanks",clicker:get_player_name())
		aliveai.invadd(self,stack:get_name(),stack:get_count())
		inv:set_stack("main", i,nil)
		return self
	elseif self.dying then
		return
	end
	
	if stack:get_name()=="aliveai_minecontroller:controller" then return end

	aliveai.invadd(self,stack:get_name(),stack:get_count())

	if stack:get_name()=="default:diamond" and aliveai.team(clicker)==self.team then
		self.taskstep=3
		self.task="..."
		aliveai.task_build(self)
		aliveai.say(self,"ok, im a guard")
		self.namecolor="0000ff55"
		aliveai.showtext(self,"Guard")
		self.home=aliveai.roundpos(self.object:get_pos())
		aliveai.showstatus(self,"guard")
		inv:set_stack("main", i,nil)
		return self
	end

	if self.need then
		local name=stack:get_name()
		for ii, vv in pairs(self.need) do
			if vv.item==name or vv.search==name then
				aliveai.known(self,clicker,"member")
				self.mood=self.mood+2
				aliveai.sayrnd(self,"thanks",clicker:get_player_name())
				break
			end
		end
	end
	inv:set_stack("main", i,nil)
	return self
end

aliveai.invadd=function(self,add,num,nfeedback)
-- inventory
	if not (add and num) or add=="" or num=="" or add=="air" then return self end
	if num>1 then self.mood=self.mood+1 end

	if self.inv[add] then
		self.inv[add]=self.inv[add]+num
		self.lastitem_name=add
		self.lastitem_count=self.inv[add]
	else
		self.inv[add]=num
	end
	if self.inv[add]<=0 then
		self.inv[add]=nil
	else
		aliveai.eat(self)
	end
-- needs
	if self.need and self.need[add] then
		if num<0 then num=num*-1 end
		self.need[add].num=self.need[add].num-num
		if self.need[add].num<=0 then self.need[add]=nil end
	end
--feedback

	if self.tools=="" then
		if minetest.registered_tools[add] then
			if minetest.registered_tools[add].tool_capabilities then
				local tool=minetest.registered_tools[add].tool_capabilities
				if tool.damage_groups and tool.damage_groups.fleshy and tool.damage_groups.fleshy> self.dmg then
					self.dmg=tool.damage_groups.fleshy
				end
			elseif minetest.registered_tools[add].on_use then
				self.tools={add}
				self.tool_near=1
				self.savetool=1
			end
		elseif minetest.registered_craftitems[add] then
			if minetest.registered_craftitems[add].tool_capabilities then
				local tool=minetest.registered_craftitems[add].tool_capabilities
				if tool.damage_groups and tool.damage_groups.fleshy and tool.damage_groups.fleshy> self.dmg then
					self.dmg=tool.damage_groups.fleshy
				end
			elseif minetest.registered_craftitems[add].on_use and minetest.get_item_group(add,"aliveai_eatable")==0 then
				self.tools={add}
				self.tool_near=1
				self.savetool=1
			end
		end
	end




	if aliveai.armor then aliveai.armor(self,{item=add}) end
	if aliveai.wieldviewr and not nfeedback then aliveai.wieldviewr(self,add) end

	aliveai.crafttools(self,add)
	if self.need and not nfeedback then aliveai.haveneed(self,true) end
	return self
end

aliveai.invhave=function(self,name,n,getnum)
		if self.creative==1 and getnum then
			return n
		elseif self.creative==1 then
			self.need=nil
			return true
		end
		local group=name
		local count=0
		if group~=name then-- only for namecuts
			for nm, s in pairs(self.inv) do
				if minetest.get_item_group(nm, group)>0 then 
					count=count+s
				end
			end
		elseif self.need and self.crafting==1 then
			-- if its a group, return an item/node
			name=aliveai.crafttoneed(self,name,true)
		end
		if getnum then
			if count>0 then return count end
			return self.inv[name] or 0
		end
		if count>0 and count>=n then
			return true
		end
		if self.inv[name]==nil then
			return false
		elseif n>self.inv[name] then
			return false
		end
		return true
end

aliveai.newneed=function(self,item,num,search,type)
	if self.creative==1 then return end
	if not self.need then self.need={} end
	search=search or ""
	num=num or 1
	if self.ignore_item[item] or (self.need[item] and self.need[item].search==search) or aliveai.invhave(self,item,num) then
		return
	end
	if type==nil then
		type="item"
		if minetest.registered_items[item] then type="item" end
		if minetest.registered_nodes[item] then type="node" end
	end
-- some extra help for the bot
	if item=="default:chest"			then search="default:chest" type="node" end
	if item=="default:chest_locked"		then search="default:chest_locked" type="node" end
	if item=="default:glass"			then search="group:sand" type="node" end
	if item=="default:wood"			then search="group:tree" type="node" end
	if item=="default:stone"			then item="default:cobble" search="group:stone" type="node" end
	if item=="default:bush_stem"		then search="group:tree" item="default:wood" type="node" end
	if item=="default:acacia_bush_stem"		then search="group:tree" item="default:wood" type="node" end
	if item=="default:iron_lump"			then item="default:steel_ingot" end
	if item=="default:copper_lump"		then item="default:copper_ingot" end
	if item=="default:gold_lump"			then item="default:gold_ingot" end
	if item=="default:stone"			then search="group:stone" end
	if item=="default:leaves"			then search="group:leaves" end
	if item=="default:dirt"			then search="group:soil" end
	if item=="wool:white"			then search="farming:cotton_8" end
	if item=="wool:blue"			then search="farming:cotton_8" end
	if item=="wool:red"			then search="farming:cotton_8" end
	if item=="air"				then return self end
	self.need[item]={num=num,item=item,search=search,type=type}
	
	if not self.mine then
		self.mine={target={},status="search"}
		aliveai.showstatus(self,"mine",4)
	end
	return self
end

aliveai.haveneed=function(self,craft)
	if self.creative==1 then return nil end
	if self.need then
		local have={}
		local name2=""
		local n=true
		for name, need in pairs(self.need) do
			n=false
			if aliveai.invhave(self,need.item,need.num) then
				self.need[name]=nil
				for name2, count2 in pairs(self.need) do
					return self
				end
				n=true
			elseif craft and self.crafting==1 then
				aliveai.crafting(self,need.item,1,need.num)
			end
		end
		if n then
			self.need=nil
			return nil,self
		end
		return self
	end
	return nil
end

aliveai.place=function(self,pos,name)
	local n=minetest.registered_nodes[minetest.get_node(pos).name]
	if minetest.registered_nodes[name] and aliveai.invhave(self,name,1) and n and n.buildable_to and not aliveai.protected(pos,self) then
		local name=name
		if self.inv[name] or self.creative==1 then
			--if minetest.registered_nodes[name] and
			--(minetest.registered_nodes[name].after_place_node
			--or minetest.registered_nodes[name].on_construct 
			--or minetest.registered_nodes[name].on_destruct) then
				--minetest.registered_nodes[name].on_place(ItemStack(name), aliveai.createuser(self), {under=pos,above={x=pos.x,y=pos.y+0.5,z=pos.z}})
				--minetest.place_node(pos, {name=name})
			--else
				minetest.set_node(pos, {name=name})
				if aliveai.def(name,"on_construct") then minetest.registered_nodes[name].on_construct(pos) end


			--end

			if self.creative==0 then aliveai.showstatus(self,name .." left: " .. self.inv[name],4) end
			aliveai.invadd(self,name,-1,true)
			return self
		end
		for node, c in pairs(self.inv) do
			if minetest.get_item_group(node, name)>0 then
				minetest.set_node(pos, {name=node})
				aliveai.showstatus(self,name .." left: " .. (self.inv[node]-1),4)
				aliveai.invadd(self,node,-1)
				return self
			end
		end
	else
		return nil
	end
end

aliveai.dig=function(self,pos)
	if minetest.is_protected(pos,"")==false and aliveai.protected(pos,self)==false and minetest.get_node(pos) then
		local name=minetest.get_node(pos).name
		if name=="air" then return true end
-- have inventory/owned
		local meta = minetest.get_meta(pos)
		local inv = meta:get_inventory()
		local owner=meta:get_string("owner")
		if meta:get_int("owner")==1 or owner=="" or owner==self.botname then
			if inv and not inv:is_empty("main") then
				for i=1,inv:get_size("main"),1 do
					local it=inv:get_stack("main",i):get_name()
					local co=inv:get_stack("main",i):get_count()
					inv:set_stack("main",i,nil)
					aliveai.spawnpickup(pos,it,co)
				end
			end
		else
			aliveai.ignorenode(self,pos)
			return false
		end
--dig + drops
		local n=1
		local drop=aliveai.digdrop(pos)
		if drop==nil then
			minetest.remove_node(pos)
			minetest.check_for_falling(pos)
		end
		if not drop then return false end
		if drop.name~=nil then
			minetest.remove_node(pos)
			minetest.check_for_falling(pos)
		end
		if minetest.get_node(pos).name~="air" then
			aliveai.ignorenode(self,pos)
			return self
		end
		aliveai.showstatus(self,"dig " .. name,4)
		aliveai.invadd(self,drop.name,drop.n)
		self.on_dig(self,pos,drop.name,drop.n)
-- if dug was added need
		if self.need and self.need[name] and self.need[name]==1 then
			self.need[name]=nil
		end
		return true
	end
	return false
end

aliveai.digdrop=function(pos)
	local node
	if minetest.registered_nodes[pos] then
		node=minetest.registered_nodes[pos]
	elseif pos and pos.x and pos.y and pos.z then
		node=minetest.registered_nodes[minetest.get_node(pos).name]
	else
		return nil
	end
-- have drop
	if not node then
		return nil
	elseif node.drop then
		local n=1
		local name=node.name
-- string drop
		if type(node.drop)=="string" then
			if node.drop=="" or node.groups.unbreakable then return nil end
			name=node.drop
			if string.find(name," ")~=nil then
				local sp=name.split(name," ")
				name=sp[1]
				n=tonumber(sp[2])
	
			end
			return {name=name,n=n}
		end
-- advanced drop
		if not (type(node.drop)=="table" and node.drop.items) then
			return {name=name,n=n}
		end
		local maxitems=node.drop.max_items or 1
		local items={}
		n=0
		for i, v in pairs(node.drop.items) do
				n=n+1
				items[n]={}
				if v.rarity then
					items[n].rnd=v.rarity
				end
				if v.items then
					items[n].items={}
					if type(v.items)=="table" then
						items[n].name=v.items[1]
					else
						items[n].name=v.items
					end
					items[n].n=1
					if string.find(items[n].name," ")~=nil then
						local sp=items[n].name.split(items[n].name," ")
						items[n].name=sp[1]
						items[n].n=tonumber(sp[2])
					end
				end
		end
		local rr=0
		for i=1,n,1 do
			if items[i] and items[i].name and items[i].rnd and aliveai.random(1,items[i].rnd)==1 then
				return {name=items[i].name,n=items[i].n}
			elseif items[i] and items[i].name and not items[i].rnd then
				return {name=items[i].name,n=items[i].n}
			end
		end
	else
		return {name=node.name,n=1}
	end
end

aliveai.eat=function(self)
	local hp=aliveai.gethp(self.object)
	if hp<=0 or hp>=self.hp_max then
		return nil
	end
	local ohp=hp
	for i, h in pairs(self.inv) do
		local eat=minetest.get_item_group(i,"aliveai_eatable")
		if eat>0 then
			for i2=1,h,1 do
				hp=hp+eat
				if hp>=self.hp_max then
					self.inv[i]=h-i2
					if self.inv[i]<=0 then self.inv[i]=nil end
					self.object:set_hp(self.hp_max)
					self.hp=self.hp_max
					aliveai.showhp(self,true)
					aliveai.showstatus(self,"ate, hp now " .. self.hp)
					return
				end
			end
			self.inv[i]=nil
		end
	end
	if ohp~=hp then
		self.object:set_hp(hp)
		self.hp=hp
		aliveai.showhp(self,true)
		aliveai.showstatus(self,"ate, hp now " .. self.hp)
	end
	return self
end

aliveai.crafting=function(self,name,norecraft,neednum)

	if self.crafting~=1 or name==nil or aliveai.enable_build==false then return false end
	neednum=neednum or 1
	if not norecraft then norecraft=0 end
	norecraft=norecraft+1
	if norecraft>5 then return self end
	name=name
	local c=minetest.get_craft_recipe(name)
	local n=1
	local relist1={}
	local relist2={}
	local list=c.items
	local output=c.output
--if group or burn
	if not c.output then 
		local group=name
		output=group
		local old=output
		for i, s in pairs(self.inv) do
			local from=minetest.get_craft_result({ method = "normal", width = 1, items = { ItemStack(i)}})
			local burn=minetest.get_craft_result({ method = "cooking", width = 3, items = { ItemStack(i)}})
			if (from and from.item) or (burn and burn.item) then
				local a1=from.item:to_table()
				local a2=burn.item:to_table()
				if a2~=nil and a2.name and aliveai.invhave(self,i,neednum) then -- cooking
					local have=s
					local take=neednum
					if take>have then
						local l=s-take
						take=take-l
					end
					aliveai.invadd(self,i,take*-1,true)
					aliveai.invadd(self,a2.name,take, true)
					return self
				end
				if a1~=nil and minetest.get_item_group(a1.name, group)>0 then
					list={i}
					output=a1.name
					n=a1.count
					break
				end
			end
		end
		if old==output then
			return false
		end
	end
-- collect items to remove
	if not list then return end
	for i, v in pairs(list) do
		local gr=v
		if not relist1[gr] then relist1[gr]=0 end
		relist1[gr]=relist1[gr]+1
	end
	if not relist1 then return end
-- check if list can be removed, or try to craft
	local nothaveall=false
	for i, v in pairs(relist1) do
		local ii=i
		if self.need and string.find(ii,"group:",1)~=nil then
			ii=aliveai.crafttoneed(self,ii,true)
		end
		if not aliveai.invhave(self,ii,v) then
			local getc
			if self.need then getc=aliveai.crafttoneed(self,ii,false,v) end
			if getc then aliveai.crafting(self,getc,norecraft,v) end
			nothaveall=true
		end
		relist2[ii]=v
	end
	if nothaveall or not relist2 then return self end
-- remove list
	for i, v in pairs(relist2) do
		if self.inv[i]==nil then
			for ii, vv in pairs(self.inv) do
				if minetest.get_item_group(ii, i)>0 or minetest.get_item_group(ii, i)>0 then
					aliveai.invadd(self,ii,v*-1,true)	
				end
			end
		else
			aliveai.invadd(self,i,v*-1,true)
		end
	end
	aliveai.invadd(self,name,n,true)
	return self
end

aliveai.getmaxstack=function(a)
	if a==nil or a=="" then return 1 end
	local b
	if minetest.registered_nodes[a] then
		b=minetest.registered_nodes[a]
	elseif minetest.registered_items[a] then
		b=minetest.registered_items[a]
	elseif minetest.registered_craftitems[a] then
		b=minetest.registered_craftitems[a]
	elseif minetest.registered_tools[a] then
		b=minetest.registered_tools[a]
	end

	if not b then return 1 end
	return b.stack_max
end

aliveai.spawnpickup=function(pos,name,n,self)
	if (name==nil or name=="") or
	(minetest.registered_nodes[name]==nil
	and minetest.registered_items[name]==nil
	and minetest.registered_craftitems[name]==nil
	and minetest.registered_tools[name]==nil) then return end
	if n==nil or tonumber(n)==nil or n==0 then n=1 end
	local ob=minetest.add_item(pos, name .." ".. n)
	if self then ob:get_luaentity().dropped_by=self.botname end
	ob:set_velocity({x = math.random(-1, 1),y=5,z = math.random(-1, 1)})
	minetest.after(3, function(ob)
		if ob and ob:get_luaentity() then
			local pos=ob:get_pos()
			local n=minetest.get_node(pos)
			local nr=minetest.registered_nodes[n.name]
			if nr and (nr.damage_per_second>0 or minetest.get_item_group(n.name,"igniter")>0 or minetest.get_item_group(n.name,"lava")>0) then
				ob:punch(ob, 1, "default:sword_wood", nil)
				minetest.add_particlespawner({
				amount = 1,
				time =0.2,
				minpos = {x=pos.x-1, y=pos.y, z=pos.z-1},
				maxpos = {x=pos.x+1, y=pos.y, z=pos.z+1},
				minvel = {x=0, y=0, z=0},
				maxvel = {x=0, y=math.random(3,6), z=0},
				minacc = {x=0, y=2, z=0},
				maxacc = {x=0, y=0, z=0},
				minexptime = 1,
				maxexptime = 3,
				minsize = 3,
				maxsize = 8,
				texture = "default_item_smoke.png",
				collisiondetection = true,
		})
			end
		end
	end,ob)

end

aliveai.invdropall=function(self)
	local pos=self.object:get_pos()
	local c=0
	local max
	aliveai.showstatus(self,"drop all items")
	if not self.inv then aliveai.kill(self) return self end
	for i, itt in pairs(self.inv) do
		max=aliveai.getmaxstack(i)
		if i and itt<=max then
			aliveai.spawnpickup(pos,i,itt,self)
		else
			local io=itt
			for b=1,itt, 1 do
				if io>max then
					io=io-max
					aliveai.spawnpickup(pos,i,max,self)
				else
					aliveai.spawnpickup(pos,i,io,self)
					break
				end
			end
		end
	end
	self.inv={}
	return self
end

aliveai.pickup=function(self,rnd)
	if self.pickuping~=1 then return self end
	if not self.pickupgoto then
		if not rnd and math.random(0,5)>1 then return self end
	end
	self.pickupgoto=nil
	if self.isrnd and not rnd then
		local pos=self.object:get_pos()
		pos.y=pos.y-1
		for _, ob in ipairs(minetest.get_objects_inside_radius(pos, self.distance)) do
			if ob and ob:get_luaentity() and ob:get_luaentity().name=="__builtin:item" then
				local pos2=ob:get_pos()
				if aliveai.visiable(self,pos2) then
					aliveai.lookat(self,pos2)
					aliveai.walk(self)
					self.pickupgoto=true
					aliveai.showstatus(self,"goto item")
					aliveai.showpath(pos2,3)
					break
				end
			end
		end
	end
	local pos=self.object:get_pos()
	for _, ob in ipairs(minetest.get_objects_inside_radius(pos, self.arm)) do
		if ob and ob:get_luaentity() and ob:get_luaentity().name=="__builtin:item" then
			local item=ob:get_luaentity().itemstring
			local droppedby=ob:get_luaentity().dropped_by
			local n=1
			if string.find(item," ")~=nil then
				local sp=item.split(item," ")
				item=sp[1]
				n=tonumber(sp[2])
			end
			if item==nil then
				ob:set_hp(0)
				ob:punch(self.object, 1, "default:sword_wood", nil)
				return self
			end
			if droppedby~=nil then
				local player=minetest.get_player_by_name(droppedby)
				if self.need and self.need[item] then
					if not self.fight and not self.fly and player then
						aliveai.known(self,player,"member")
						aliveai.sayrnd(self,"thanks",droppedby)
					end
					if self.fight and aliveai.getknown(self,self.fight,"fight") then
						aliveai.known(self,self.fight,"")
						aliveai.sayrnd(self,"thanks",droppedby)
					end
				end
			end
			aliveai.invadd(self,item,n)
			aliveai.punch(self,ob,1)
			self.pickupgoto=nil
			aliveai.showstatus(self,"picked up " .. item)	
		end
	end
end

minetest.after(0, function()
	aliveai.inventorycreate()
end)
aliveai.inventorycreate=function()
aliveai.inventory=minetest.create_detached_inventory("main", {
	allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
		return count
	end,
	allow_put = function(inv, listname, index, stack, player)
		return stack:get_count()
	end,
	allow_take = function(inv, listname, index, stack, player)
		return stack:get_count()
	end,
	})
	aliveai.inventory:set_size("main", 16)
end

aliveai.clearinventory=function(self)
	local pos
	if self then pos=self.object:get_pos() end
	local inv = minetest.get_inventory({type="detached", name="main"})
	for i=1,inv:get_size("main"),1 do
		local it=inv:get_stack("main",i):get_name()
		local co=inv:get_stack("main",i):get_count()
		inv:set_stack("main",i,nil)
		if it~="" and pos and pos.x and type(self.tools)=="table" then
			local nohaveit=true
			for ii, name in pairs(self.tools) do
				if name==it then
					nohaveit=false
					break
				end
			end
			if nohaveit then  aliveai.spawnpickup(pos,it,co,self) end
		end
	end
end

aliveai.re=function(a)
	return (function() return a end)
end
	
aliveai.use=function(self)
	if self.tools==nil or type(self.tools)~="table" then return self end

	if self.tools[1] and not self.tools[2] then
		aliveai.tool_handler(self,self.tools[1])
	end

	local inv=minetest.get_inventory({type="detached", name="main"})
	local n=0
	local tool=""
	local pointed_thing={type="nothing"}
	local pos=self.object:get_pos()
	for i, name in pairs(self.tools) do
		n=n+1
		if n==self.tool_index then
			if not (minetest.registered_tools[name] and minetest.registered_tools[name].on_use) then print("error: tried to use " .. name .." as a tool, but doesn't have the on_use() function") return self end
			tool=name
		end
		inv:set_stack("main", n, ItemStack(name .. " " .. 1))
	end
	local user=aliveai.createuser(self,self.tool_index)
	if self.fight then
		local range=self.arm
		if minetest.registered_tools[tool] and minetest.registered_tools[tool].range then range=minetest.registered_tools[tool].range end
		local fpos=self.fight:get_pos()
		local d=aliveai.distance(self,fpos)
		if d<self.distance and aliveai.visiable(self,fpos) then
			local dir=aliveai.get_dir(self,fpos)
			user.get_look_dir=aliveai.re(dir)
			if d<=range then
				pointed_thing.type="object"
				pointed_thing.ref=self.fight
			end
		end
	end
	local stack=ItemStack(inv:get_stack("main", self.tool_index))
	aliveai.showstatus(self,"use tool: " .. stack:get_name())
	if not minetest.registered_tools[tool] then return end

	if aliveai.wieldviewr then aliveai.wieldviewr(self,tool) end

	minetest.log("aliveai:" .. self.botname .." uses " .. tool)

	local error
	error,stack=pcall(minetest.registered_tools[tool].on_use,unpack{stack,user,pointed_thing})

	if error==true and self.tool_reuse==1 then
		tool=stack:get_name()
		minetest.after(0.1, function(self,tool,inv,stack,user,pointed_thing)
			minetest.registered_tools[tool].on_use(stack,user,pointed_thing)
			aliveai.clearinventory(self)
		end,self,tool,inv,stack,user,pointed_thing)
	else
		aliveai.clearinventory(self)
	end
	return self
end

aliveai.spawnbones=function(self)
	if not self and self.object then return end
	local pos=self.object:get_pos()
	pos={x=pos.x,y=pos.y+0.5,z=pos.z}
	if self.dropbones==1 and aliveai.set_bones and aliveai.bones and aliveai.def(pos,"buildable_to") and not minetest.is_protected(pos,"") then
		minetest.set_node(pos,{name="bones:bones"})
		local meta=minetest.get_meta(pos)
		local inv=meta:get_inventory()
		inv:set_size("main", 32)
		meta:set_string("infotext", self.botname .."'s bones")
		meta:set_string("formspec",
		"size[8,8]" ..
		"list[context;main;0,0;8,4;]" ..
		"list[current_player;main;0,4;8,4;]" ..
		"listring[current_player;main]" ..
		"listring[current_name;main]")
		for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 3)) do
			local en=ob:get_luaentity()
			if en and en.name=="__builtin:item" and en.dropped_by==self.botname then
				if inv:room_for_item("main", en.itemstring) then
					inv:add_item("main", en.itemstring)
					aliveai.kill(en)
				else
					return
				end
			end
		end
	end
end



aliveai.createuser=function(self,index)
	index=index or 1
	local yaw=self.object:get_yaw()
	if type(yaw)~="number" then yaw=0 end
	yaw=yaw+1.575
	local pos=self.object:get_pos()
	local inv=minetest.get_inventory({type="detached", name="main"})
	return {
		get_player_control=aliveai.re({sneak=false,up=false,down=false,left=false,right=false}),
		get_inventory=aliveai.re({contains_item=aliveai.re(true)}),
		get_luaentity=aliveai.re(self.object),
		get_player_name=aliveai.re(self.botname),
		get_look_horizontal=aliveai.re(0),
		set_look_horizontal=aliveai.re(0),
		set_animation=aliveai.re(),
		set_eye_offset=aliveai.re(),
		get_look_dir=aliveai.re(aliveai.get_dir(self,aliveai.pointat(self))),
		get_look_pitch=aliveai.re(math.pi/2),
		get_look_yaw=aliveai.re(self.object:get_yaw()),
		get_player_control=aliveai.re({jump=false,right=false,left=false,LMB=false,RMB=false,sneak=false,aux1=false,down=false,up=false}),
		get_player_control_bits=aliveai.re(0),
		is_player=aliveai.re(true),
		set_hp=aliveai.re(),
		get_hp=aliveai.re(self.object:get_hp()),
		get_breath=aliveai.re(11),
		get_inventory_formspec=aliveai.re(""),
		set_inventory_formspec=aliveai.re(0),
		get_inventory=aliveai.re(inv),
		get_wielded_item=aliveai.re(inv:get_stack("main", index)),
		get_wield_index=aliveai.re(self.tool_index),
		get_wield_list=aliveai.re("main"),
		set_wielded_item=function(self, item)
			items=item
			inv:set_stack("main", items, item)
		end,
		setpos=aliveai.re(),
		set_pos=aliveai.re(),
		getpos=aliveai.re(pos),
		get_pos=aliveai.re(pos),
		moveto=aliveai.re(),
		punch=aliveai.re(),
		remove=aliveai.re(),
		right_click=aliveai.re(),
		set_properties=aliveai.re(),
		set_animation=aliveai.re(),
		get_attach=aliveai.re(),
		set_attach=aliveai.re(),
		set_detach=aliveai.re(),
		set_bone_position=aliveai.re(),
		hud_change=aliveai.re(),
	}
end


aliveai.register_buildings_spawner("Copy building",{
		on_use = function(itemstack, user, pointed_thing)
			if pointed_thing.type=="node" then
				aliveai.form(user:get_player_name())
			end
			return itemstack
		end,
		on_place = function(itemstack, user, pointed_thing)
			if pointed_thing.type=="node" then
				local name=user:get_player_name()
				if not aliveai.buildingtool then
					aliveai.form(name)
					return itemstack
				end
				local pos=pointed_thing.under
				local last=""
				local node=""
				local nodes=""
				local count=0
				local need={}
				local dir=minetest.dir_to_facedir(user:get_look_dir())
				local z1=1
				local x1=1
				if dir==1 then x1=1 z1=1 end
				if dir==3 then x1=-1 z1=-1 end
				if dir==0 then x1=-1 z1=1 end
				if dir==2 then x1=1 z1=-1 end
				local toy=aliveai.buildingtool.y
				local tox=aliveai.buildingtool.x*x1
				local toz=aliveai.buildingtool.z*z1
				local status=false
				if aliveai.status==false then status=true end
				aliveai.status=true

				for y=0,toy,1 do
					for x=0,tox,x1 do
						for z=0,toz,z1 do
							local p={x=pos.x+x,y=pos.y+y,z=pos.z+z}
							node=minetest.get_node(p).name
							if last=="" then last=node end
							if node~="a" then
								if not need[node] then need[node]=0 end
								need[node]=need[node]+1
							end
							if (y==0 or y==toy) or (x==0 or x==tox) or (z==0 or z==toz) then
								aliveai.showpath(p,2)
							end

							if node~=last then
								nodes=nodes ..last .." " .. count .. "!"
								count=0
							end
							count=count+1
							last=node
							if y==toy and x==tox and z==toz and last~="a" then
								nodes=nodes ..last .." " .. count .. "!"
								count=0
							end
						end
					end
				end
			if status then aliveai.status=false end
			local t=""
			for n, v in pairs(need) do
				t=t .. n.." " ..v .."!"
			end
			nodes=aliveai.buildingtool.x .." " .. aliveai.buildingtool.y .." " .. aliveai.buildingtool.z .. "+++" .. t .."+" .. nodes
			aliveai.form(name,nodes)
			return itemstack
			end
		end
})

aliveai.register_buildings_spawner("Generate building",{
	on_use=function(itemstack, user, pointed_thing)
		if pointed_thing.type=="node" then
			local pos=pointed_thing.above
			local name=user:get_player_name()
			for y=0,7,1 do
			for x=0,10,1 do
			for z=0,10,1 do
				local p={x=pos.x+x,y=pos.y+y,z=pos.z+z}
				local node=minetest.get_node(p)
				if not node then
					minetest.set_node(p,{name="air"})
					node=minetest.get_node(p)
				end
				if minetest.registered_nodes[node.name].buildable_to==false or minetest.is_protected(p,name) then
					minetest.chat_send_player(name, "aliveai: area not able: " .. node.name)
					return itemstack
				end
			end
			end
			end
			aliveai.generate_house(pos)
		end
	end
})