

local S = minetest.get_translator(minetest.get_current_modname())

dofile(minetest.get_modpath("infinity") .. "/gauntlets.lua")
--CORE--
minetest.register_craftitem("infinity:core", {
    description = "gauntlet core",
    inventory_image = "infinity_core.png",
})

dofile(minetest.get_modpath("infinity") .. "/stones.lua")

--CODE BORROWED FROM THE BUILD SPAWNER FOR BASE BUILDER--

minetest.register_node("infinity:base_builder_generator", {
    description = "Base Builder(Place to get a base)",
 
    tiles = {
	"infinity_DIRTGauntlet.png",
	"infinity_DIRT.png",
	"infinity_DIRTGauntlet.png",
	"infinity_DIRTGauntlet.png",
	"infinity_DIRTGauntlet.png",
	"infinity_DIRTGauntlet.png"
},
	on_place = function(itemstack, placer, pointed_thing)
		if not placer or not pointed_thing.above then
			return itemstack
		end
		
		local pos = pointed_thing.above
		local p = placer:get_pos()  -- Get the placer's position
		local meta = minetest.get_meta(pos)
		local owner = meta:get_string("owner")  -- Assume you store owner info in metadata
		
		if minetest.is_protected(pos, placer:get_player_name())
		   or (owner ~= "" and owner ~= placer:get_player_name()) then
			minetest.chat_send_player(placer:get_player_name(), "You don't have permission to build here.")
			return itemstack
		end

		local file = io.open(minetest.get_modpath("infinity").."/schemes/Gauntleet.we")
		local value = file:read("*a")
		file:close()

		p.y = p.y - 1
		p.x = p.x - 3
		p.z = p.z - 2
		local count = worldedit.deserialize(pos, value)
		itemstack:take_item()

		return itemstack
	end
})

minetest.register_node("infinity:instructions_chest", {
    description = "Place to Learn the Ways of the Gauntlet...",
tiles = {
	"default_chest_top.png",
	"default_chest_top.png",
	"default_chest_side.png",
	"default_chest_side.png",
	"default_chest_side.png",
	"default_chest_front.png"
},
	on_place = function(itemstack, placer, pointed_thing)
		if not placer or not pointed_thing.above then
			return itemstack
		end
		
		local pos = pointed_thing.above
		local p = placer:get_pos()  -- Get the placer's position
		local meta = minetest.get_meta(pos)
		local owner = meta:get_string("owner")  -- Assume you store owner info in metadata
		
		if minetest.is_protected(pos, placer:get_player_name())
		   or (owner ~= "" and owner ~= placer:get_player_name()) then
			minetest.chat_send_player(placer:get_player_name(), "You don't have permission to build here.")
			return itemstack
		end

		local file = io.open(minetest.get_modpath("infinity").."/schemes/chest.we")
		local value = file:read("*a")
		file:close()

		p.y = p.y
		p.x = p.x 
		p.z = p.z
		local count = worldedit.deserialize(pos, value)
		itemstack:take_item()

		return itemstack
	end
})




--CODE BORROWED FROM NSSM FOR POWERSHOT--
local default_dir = {x = 1, y = 1, z = 1}

-- Function used to shoot:
local function weapons_shot(itemstack, placer, pointed_thing, velocity, name)

	local dir = placer:get_look_dir()
	local playerpos = placer:get_pos()
	local obj = minetest.add_entity({
		x = playerpos.x + dir.x,
		y = playerpos.y + 2 + dir.y,
		z = playerpos.z + dir.z
	}, "infinity:" .. name)

	local vec = {x = dir.x * velocity, y = dir.y * velocity, z = dir.z * velocity}

	obj:set_velocity(vec)

	return itemstack
end


local function hit(pos, self)

	local node = nssm:node_ok(pos).name

	self.hit_node(self, pos, node)
	self.object:remove()

	return
end


local function activate_balls(pos)

	local radius = 50
	local objects = minetest.get_objects_inside_radius(pos, radius)

	for _,obj in ipairs(objects) do

		if obj:get_luaentity()
		and obj:get_luaentity().name == "nssm:hellzone_grenade" then
			obj:get_luaentity().move = 1
		end
	end
end


local function search_on_step2(
	self,
	dtime,	  --used to count time
	max_time,   --after this amount of time the entity is removec
	radius,	 --radius in which look for entities to follow
	vel)		--velocity of the projectile

	local pos = self.object:get_pos()

	--Disappear after a certain time
	if self.life_time == 0 then
		self.life_time = os.time()
	end

	if os.time() - self.life_time > max_time then
		self.object:remove()
		return
	end

	--Look for an entity to follow
	local objects = minetest.get_objects_inside_radius(pos, radius)
	local min_dist = 100
	local obj_min = nil
	local obj_p = nil
	local vec_min = nil

	for _,obj in ipairs(objects) do

		if (obj:is_player()) then
		elseif (obj:get_luaentity()
		and obj:get_luaentity().name ~= "__builtin:item"
		and obj:get_luaentity().name ~= self.object:get_luaentity().name) then

			obj_p = obj:get_pos()

			local vec = {x = obj_p.x - pos.x, y = obj_p.y - pos.y, z = obj_p.z - pos.z}
			local dist = (vec.x ^ 2 + vec.y ^ 2 + vec.z ^ 2) ^ 0.5

			if (dist < min_dist) then
				min_dist = dist
				obj_min = obj
				vec_min = vec
			end
		end
	end

	-- Found an entity to follow:
	if obj_min ~= nil then

		local new_vel = {x = 0, y = 0, z = 0}

		local dir = 0
		local max_diff = 0

		if max_diff < math.abs(vec_min.x) then
			dir = 1
			max_diff = math.abs(vec_min.x)
		end

		if max_diff < math.abs(vec_min.y) then
			dir = 2
			max_diff = math.abs(vec_min.y)
		end

		if max_diff < math.abs(vec_min.z) then
			dir = 3
			max_diff = math.abs(vec_min.z)
		end

		vec_min.x = (vec_min.x / max_diff) * vel
		vec_min.y = (vec_min.y / max_diff) * vel
		vec_min.z = (vec_min.z / max_diff) * vel

		obj_p = obj_min:get_pos()

		if min_dist <= 8 and self.move == 0 then
			self.object:set_velocity({x = 0, y = 0, z = 0})
		elseif min_dist <= 1 and self.move == 1 then
			hit(pos, self)
		else
			self.object:set_velocity(vec_min)
		end
	end

	local n = minetest.get_node(pos).name

	if n ~= "air" and n ~= "default:water_source" and n ~= "default:water_flowing" then
		hit(pos, self)
	end
end


-- on_step function able to follow the mobs
local function search_on_step(
	self,
	dtime,	  --used to count time
	max_time,   --after this amount of time the entity is removed
	radius,	 --radius in which look for entities to follow
	vel)		--velocity of the projectile

	local pos = self.object:get_pos()

	-- Disappear after a certain time
	if self.life_time == 0 then
		self.life_time = os.time()
	end

	if os.time() - self.life_time > max_time then
		self.object:remove()
		return
	end

	-- Look for an entity to follow
	local objects = minetest.get_objects_inside_radius(pos, radius)
	local min_dist = 100
	local obj_min = nil
	local obj_p = nil
	local vec_min = nil

	for _,obj in ipairs(objects) do

		if (obj:is_player()) then
		elseif (obj:get_luaentity()
		and obj:get_luaentity().name ~= "__builtin:item"
		and obj:get_luaentity().name ~= self.object:get_luaentity().name) then

			obj_p = obj:get_pos()

			local vec = {x = obj_p.x - pos.x, y = obj_p.y - pos.y, z = obj_p.z - pos.z}
			local dist = (vec.x ^ 2 + vec.y ^ 2 + vec.z ^ 2) ^ 0.5

			if dist < min_dist then
				min_dist = dist
				obj_min = obj
				vec_min = vec
			end
		end
	end

	-- Found an entity to follow:
	if obj_min ~= nil then

		local new_vel = {x = 0, y = 0, z = 0}

		local dir = 0
		local max_diff = 0

		if max_diff < math.abs(vec_min.x) then
			dir = 1
			max_diff = math.abs(vec_min.x)
		end

		if max_diff < math.abs(vec_min.y) then
			dir = 2
			max_diff = math.abs(vec_min.y)
		end

		if max_diff < math.abs(vec_min.z) then
			dir = 3
			max_diff = math.abs(vec_min.z)
		end

		vec_min.x = (vec_min.x/max_diff)*vel
		vec_min.y = (vec_min.y/max_diff)*vel
		vec_min.z = (vec_min.z/max_diff)*vel

		obj_p = obj_min:get_pos()

		if min_dist < 1 then

			local node = nssm:node_ok(pos).name

			self.hit_node(self, pos, node)
			self.object:remove()

			return
		else
			self.object:set_velocity(vec_min)
		end
	end

	local n = minetest.get_node(pos).name

	if n ~= "air" and n ~= "default:water_source" and n ~= "default:water_flowing" then

		local node = nssm:node_ok(pos).name

		self.hit_node(self, pos, node)
		self.object:remove()

		return
	end
end


local function default_on_step(
	self,
	dtime,			  --used to count time
	max_time,		   --after this amount of time the entity is removec
	damage,			 --damage dealt to the entity around
	dir,				--vector to specify directions in which remove blocks
	radius,			 --radius of blocks removed aroind the projectile
	not_transparent,	--name of a block or of a group: when the projectile hit one of these blocks the function hit_node is called
	vel)				--velocity of the projectile

	local pos = self.object:get_pos()

	if self.life_time == 0 then
		self.life_time = os.time()
	end

	if os.time() - self.life_time > max_time then

		local node = nssm:node_ok(pos).name

		self.hit_node(self, pos, node)
		self.object:remove()

		return
	end

	self.timer = self.timer + dtime

	-- while going around it damages entities
	local objects = minetest.get_objects_inside_radius(pos, 2)

	if self.timer > 0.1 then

		self.timer = 0

		for _,obj in ipairs(objects) do

			if obj:get_luaentity() then

				if obj and obj:get_luaentity()
				and obj:get_luaentity().name ~= self.object:get_luaentity().name
				and obj:get_luaentity().name ~= "__builtin:item" then

					if obj:is_player() then
						obj:set_hp(obj:get_hp()-damage)
					elseif obj:get_luaentity().health then
						obj:get_luaentity().health = obj:get_luaentity().health - damage
					end
				end
			end
		end
	end

	local n = minetest.get_node(pos).name

	if n == not_transparent or n == "default:chest" or n == "default:chest_locked" or n == "infinity:instructions_chest" or minetest.get_item_group(n, not_transparent) == 1 then

		local node = nssm:node_ok(pos).name

		self.hit_node(self, pos, node)
		self.object:remove()

		return
	else
		local vec = self.object:get_velocity()
		local c = vel / 10

		--calculate how many blocks around need to be removed
		local max = 0
		local posmax = 0

		if max < math.abs(vec.x) then
			max = math.abs(vec.x)
			posmax = 1
		end

		if max < math.abs(vec.y) then
			max = math.abs(vec.y)
			posmax = 2
		end

		if max < math.abs(vec.z) then
			max = math.abs(vec.z)
			posmax = 3
		end

		local i = radius
		local j = radius
		local k = radius

		if dir.x == 0 then
			i = 0
		end

		if dir.y == 0 then
			j = 0
		end

		if dir.z == 0 then
			k = 0
		end

		if posmax==1 then
			i = 0
		end

		if posmax==2 then
			j = 0
		end

		if posmax==3 then
			k = 0
		end

		for dx = -i,i do
			for dy= -j,j do
				for dz = -k,k do

					local p = {x = pos.x + dx, y = pos.y + dy, z = pos.z + dz}

					if not minetest.is_protected(p, "")
					or not minetest.get_item_group(n, "unbreakable") == 1 then
						minetest.dig_node(p)
					end
				end
			end
		end
	end
end


--[[
Function to register new weapons: parameters:
	- name of the weapon
	- on_step function (written by you or taken from the standard one above)
	- hit_node function
	- description of the weapon
	- the velocity of the projectile
	- one material to be used in the receipt
]]
local function infinity_register_weapon(name, def)

	minetest.register_entity("infinity:"..name, {

		initial_properties = {
			textures = {"infinity_"..name..".png"},
		},

		on_step = function(self, dtime)
			def.on_step(self, dtime)
		end,

		hit_node = function(self, pos, node)
			def.hit_node(self, pos, node)
		end,

		move = def.move,
		life_time = 0,
		timer = 0,
		custom_timer = 0
	})

	minetest.register_craftitem("infinity:"..name.."_hand", {
		description = def.description,
		inventory_image = "infinity_".. name .. "_hand.png",

		on_use = function(itemstack, placer, pointed_thing)
			weapons_shot(itemstack, placer, pointed_thing, def.velocity, name)
			
			return itemstack
		end,

		on_drop = def.on_drop or function(itemstack, user, pointed_thing)
		end
	})

	minetest.register_craft({
		output = "infinity:" .. name .. "_hand",
		recipe = {
			{"", "", ""},
			{"", "infinity:stonepower", ""},
			{"", "", ""}
		}
	})
end


infinity_register_weapon("powershot", {
	velocity = 25,
	light_source = 100,
	on_step = function(self, dtime)
		default_on_step(self, dtime, 4, 20, default_dir, 1, "infinity:space_chest", 25)
	end,

	hit_node = function(self, pos, node)
		tnt.boom(pos, {damage_radius = 17.5, radius = 7.5, ignore_protection = true})
	end,


	description = "Empowered By The Power Of The Power Stone..."
})

--CODE BORROWED FROM PORTABLE CHESTS FOR SPACE CHEST--
local function drop_chest(pos, oldmetadata)
    local chest_stuff = ItemStack("infinity:space_chest")
    local meta = chest_stuff:get_meta()

    local inv = oldmetadata.inventory.main
    local empty = true
    for i, stack in ipairs(inv) do
        if stack:get_count() > 0 then
            empty = false
            break
        end
    end

    if not empty then
        local items = {}
        for listname, list in pairs(oldmetadata.inventory) do
            items[listname] = {}
            for i, stack in ipairs(list) do
                items[listname][i] = stack:to_string()
            end
        end
        meta:set_string("items", minetest.serialize(items))
    end

    minetest.add_item(pos, chest_stuff)
end


local function get_formspec_chest()
    return "size[24,15]"..
		"list[context;main;0,0.5;24,10;]"..
		"list[current_player;main;8,10.5;8,4;]"
end

minetest.register_node("infinity:space_chest", {
		description = "Space Stone Chest",
		tiles = {"infinity_space_stone_chest_top.png", "infinity_space_stone_chest_top.png", "infinity_space_stone_chest_side.png", "infinity_space_stone_chest_side.png", "infinity_space_stone_chest_side.png", "infinity_space_stone_chest_front.png"},
		groups = {cracky = 3},
		light_source = 100,
		stack_max = 100,
		paramtype2 = "facedir",
		on_blast = function() end,
		after_place_node = function(pos, placer, itemstack, pointed_thing)
			local meta = minetest.get_meta(pos)
			local inv = meta:get_inventory()
			meta:set_string("owner", placer:get_player_name())
			meta:set_string("infotext", "Chest owned by " .. placer:get_player_name())
			meta:set_string("formspec", get_formspec_chest())
			inv:set_size("main", 24*15)
        local items = minetest.deserialize(itemstack:get_meta():get_string("items"))
        if items then
            for listname, list in pairs(items) do
                for i, item in ipairs(list) do
                    inv:set_stack(listname, i, ItemStack(item))
                end
            end
        end
    end,
		
		on_rightclick = function(pos, node, placer, itemstack) 
			local meta = minetest.get_meta(pos)
			if placer:get_player_name() == meta:get_string("owner") then meta:set_string("formspec", get_formspec_chest(pos)) else meta:set_string("formspec", "") end
		end,
    on_dig = function(pos, node, digger)
        local meta = minetest.get_meta(pos)
        local inv = meta:get_inventory()
        drop_chest(pos, meta:to_table())
        minetest.remove_node(pos)
    end,
})

dofile(minetest.get_modpath("infinity") .. "/stuffiacuallycodednotgauntlets.lua")

local function register_egg(mob, desc, background, addegg, no_creative)

	local grp = {spawn_egg = 1}

	-- do NOT add this egg to creative inventory (e.g. dungeon master)
	if no_creative == true then
		grp.not_in_creative_inventory = 1
	end

	local invimg = background

	if addegg == 1 then
		invimg = "mobs_chicken_egg.png^(" .. invimg ..
			"^[mask:mobs_chicken_egg_overlay.png)"
	end

	-- does mob/entity exist
	local is_mob = minetest.registered_entities[mob]

	if not is_mob then
		print("[Mobs Redo] Spawn Egg cannot be created for " .. mob)
		return
	end

	-- register new spawn egg containing mob information (cannot be stacked)
	-- these are only created for animals and npc mobs, not monsters
if is_mob.type ~= "monster" then

	minetest.register_craftitem(":" .. mob .. "_set", {

		description = S("@1 (Tamed)", desc),
		inventory_image = invimg,
		groups = {spawn_egg = 2, not_in_creative_inventory = 1},
		stack_max = 1,

		on_place = function(itemstack, placer, pointed_thing)

			local pos = pointed_thing.above

			-- does existing on_rightclick function exist?
			local under = minetest.get_node(pointed_thing.under)
			local def = minetest.registered_nodes[under.name]

			if def and def.on_rightclick then

				return def.on_rightclick(
						pointed_thing.under, under, placer, itemstack, pointed_thing)
			end

			if pos and not minetest.is_protected(pos, placer:get_player_name()) then

				-- have we reached active mob limit


				pos.y = pos.y + 1

				local data = itemstack:get_metadata()
				local smob = minetest.add_entity(pos, mob, data)
				local ent = smob and smob:get_luaentity()

				if not ent then return end -- sanity check

				-- set owner if not a monster
				if ent.type ~= "monster" then
					ent.owner = placer:get_player_name()
					ent.tamed = true
				end

				-- since mob is unique we remove egg once spawned
			end

			return itemstack
		end
	})
end

	-- register old stackable mob egg
	minetest.register_craftitem(":" .. mob, {

		description = desc,
		inventory_image = invimg,
		groups = grp,

		on_place = function(itemstack, placer, pointed_thing)

			local pos = pointed_thing.above

			-- does existing on_rightclick function exist?
			local under = minetest.get_node(pointed_thing.under)
			local def = minetest.registered_nodes[under.name]

			if def and def.on_rightclick then

				return def.on_rightclick(
						pointed_thing.under, under, placer, itemstack, pointed_thing)
			end

			if pos and not minetest.is_protected(pos, placer:get_player_name()) then

				-- have we reached active mob limit


				pos.y = pos.y + 1

				local smob = minetest.add_entity(pos, mob)
				local ent = smob and smob:get_luaentity()

				if not ent then return end -- sanity check

				-- don't set owner if monster or sneak pressed
				if ent.type ~= "monster" and not placer:get_player_control().sneak then
					ent.owner = placer:get_player_name()
					ent.tamed = true
				end

				-- if not in creative then take item

			end

			return itemstack
		end
	})
end
mobs:register_mob("infinity:lokistaff", {
	type = "clone",
	passive = false,
	attack_type = "dogfight",
	pathfinding = true,
	reach = 20000,
	lifetime = 1,
	can_despawn = true,
	range = 20000000000,
	damage = 200000,
	hp_min = 1000,
	hp_max = 1000,
	armor = 1000,
	light_source = 10000,
	blood_texture = "infinity_mindstone.png",
	blood_amount = 1000,
	knock_back = 1,
        expirationtime = 1.25,
	collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
	visual = "mesh",
	mesh = "character.b3d",
	textures = {
		{"infinity_clone.png"},
		{"infinity_clone.png"}
	},
	fly = false,
	fast = true,
	jump = true,
	attacks_monsters = true,
	attack_animals = true,
	attack_player = false,
	follow = {"infinity:cloner"},
    on_spawn = function(self, pos)
        -- Check if the mob has been alive for more than 60 seconds
        if self.time_alive and self.time_alive > 1 then
            -- Remove the mob
            self.object:remove()
        end
    end,
})
	

register_egg("infinity:lokistaff", S("Clone Yourself With the Power Of The Mind Stone"), "infinity_cloned.png", 3)

--CODE BORROWED FROM ENDERPEARL AND TARDIS_NEW FOR TESSERACT--
infinity = {}
local t = minetest.get_translator("infinity")
local callbacks = {}

local function get_formspec_tesseract()
    return "size[10,10]"..
		"field[1,1;8,1;teleport_x;X-Cord;0]"..
		"field[1,3;8,1;teleport_y;Y-Cord;0]"..
		"field[1,5;8,1;teleport_z;Z-Cord;0]"..
		"image_button_exit[1,6.5;3,3;infinity_tesseract.png;teleport; ;false;false;infinity_tesseract.png]"
end
----------------------
-- ! Item Section ! -- 
----------------------

minetest.register_node("infinity:tesseract", {
  description = "The Tesseract Grants The Ability To Teleport With A Single Click",
  tiles = {"infinity_tesseract.png", "infinity_tesseract.png", "infinity_tesseract.png", "infinity_tesseract.png", "infinity_tesseract.png", "infinity_tesseract.png"},
  stack_max = 100,
  light_source = 100,
    drawtype = "liquid",
  range = 1000,
  on_use =
    function(_, player, pointed_thing)
      local throw_starting_pos = vector.add({x=0, y=1.5, z=0}, player:get_pos())
      local tesseract = minetest.add_entity(throw_starting_pos, "infinity:thrown_tesseract", player:get_player_name())
end,
	on_place = function(itemstack, player, pointed_thing)
		minetest.show_formspec(player:get_player_name(), "infinity:tesseract_formspec", get_formspec_tesseract() )
	end
})



------------------------
-- ! Entity Section ! -- 
------------------------

-- entity declaration

--THROWN OBJECT FOR THE TESSERACT--
minetest.register_node("infinity:infinity_zfakestonespace", {
	description = "Used for entity",
	texture = "tesseract.png",
	light_source = 40,
	groups = {not_in_creative_inventory = 1},
})

local thrown_tesseract = {
  initial_properties = {
    hp_max = 1,
    physical = true,
    collide_with_objects = false,
    collisionbox = {-0.2, -0.2, -0.2, 0.2, 0.2, 0.2},
    visual = "wielditem",
    visual_size = {x = 0.4, y = 0.4},
    textures = {"infinity:tesseract"},
    spritediv = {x = 1, y = 1},
    initial_sprite_basepos = {x = 0, y = 0},
    pointable = false,
    speed = 100,
    gravity = 15,
    damage = 0,
    lifetime = 20
  },
  player_name = ""
}


function thrown_tesseract:on_step(dtime, moveresult)  
  local collided_with_node = moveresult.collisions[1] and moveresult.collisions[1].type == "node"

  if collided_with_node then
    local player = minetest.get_player_by_name(self.player_name)

    if not player then
      self.object:remove()
      return
    elseif player:get_meta():get_string("ep_can_teleport") == "false" then
      self.object:remove()
      return
    end
    -- removing fall damage
    player:add_player_velocity(vector.multiply(player:get_player_velocity(), -1))
    player:set_pos(vector.add(self.object:get_pos(), {x = 0, y = 1, z = 0}))
    player:set_hp(player:get_hp()-self.initial_properties.damage, "infinity")
    minetest.sound_play("infinity_teleport", {max_hear_distance = 10, pos = player:get_pos()})

    for i=1, #callbacks do
      local node = minetest.get_node(moveresult.collisions[1].node_pos)
      callbacks[i](node)
    end

    self.object:remove()
  end
end



function thrown_tesseract:on_activate(staticdata)
  if not staticdata or not minetest.get_player_by_name(staticdata) then
    self.object:remove()
    return
  end

  self.player_name = staticdata
  local player = minetest.get_player_by_name(staticdata)
  local yaw = player:get_look_horizontal()
  local pitch = player:get_look_vertical()
  local dir = player:get_look_dir()

  self.object:set_rotation({x = -pitch, y = yaw, z = 0})
  self.object:set_velocity({
      x=(dir.x * self.initial_properties.speed),
      y=(dir.y * self.initial_properties.speed),
      z=(dir.z * self.initial_properties.speed),
  })
  self.object:set_acceleration({x=dir.x*-4, y=-self.initial_properties.gravity, z=dir.z*-4})

  minetest.after(self.initial_properties.lifetime, function() self.object:remove() end)
end



minetest.register_entity("infinity:thrown_tesseract", thrown_tesseract)



---------------------------
-- ! Callbacks Section ! -- 
---------------------------

-- on_teleport(hit_node)
function infinity.on_teleport(func)
  table.insert(callbacks, func)
end



-----------------------
-- ! Utils Section ! -- 
-----------------------

function infinity.block_teleport(player, duration)
  if duration then
    minetest.after(duration, function() 
      if minetest.get_player_by_name(player:get_player_name()) then
        player:get_meta():set_string("ep_can_teleport", "")
      end
    end)
  end

  player:get_meta():set_string("ep_can_teleport", "false")
end


--CODE BORROWED FROM AURORA TECH FOR VISION--
	infinity = {}

local function register_tool(name, defs, cb)
	defs.drawtype = "mesh"
	defs.node_placement_prediction = "air"

	defs.on_place = cb
	defs.on_secondary_use = cb

	defs.stack_max = defs.stack_max or 1

	minetest.register_node(name, defs)
end

local function register_tool_durability(name, defs, cb, dura, auto, cb_dead)
	local count = math.min(dura, 16)

	if auto then
		local old_cb = cb
		cb = function(itemstack, placer, pt)
			old_cb(itemstack, placer, pt)
			return infinity.damage_tool(itemstack)
		end
	end

	for i = 1, count do
		local cb = cb
		if i == 1 then cb = cb_dead end

		local factor = (i - 1) / (count - 1)
		local pixels = math.floor(factor * 16)
		local opac = 255 - math.floor(factor * 255)

		local defs = table.copy(defs)
		local groups = table.copy(defs.groups or {})
		if i ~= count then groups["not_in_creative_inventory"] = 1 end
		defs._infinity_dura = dura
		defs._infinity_name = name
		defs.groups = groups

		register_tool(name .. "_" .. i, defs, cb)
	end
end

infinity.register_tool_3d = function(name, defs, cb, dura, auto, cb_dead)
	if dura == nil then register_tool(name, defs, cb)
	else register_tool_durability(name, defs, cb, dura, auto, cb_dead) end
end

infinity.register_repair = function(tool, material, amount, return_tool)
	if return_tool == nil then return_tool = tool end

	local tool_dura = math.min(minetest.registered_nodes[tool .. "_1"]._infinity_dura, 16)

	for i = 1, tool_dura - 1 do
		for j = 1, 8 do
			local recipe = { tool .. "_" .. i }
			local res = i + amount * j

			for k = 1, j do
				table.insert(recipe, material)
			end

			minetest.register_craft({
	      type = "shapeless",
	      output = return_tool .. "_" .. math.min(res, tool_dura),
	      recipe = recipe
			})

			if res >= tool_dura then
				break
			end
		end
	end
end

infinity.damage_tool = function(itemstack)
	if not itemstack or not minetest.registered_nodes[itemstack:get_name()] then return itemstack end

	local dura = minetest.registered_nodes[itemstack:get_name()]._infinity_dura
	local name = minetest.registered_nodes[itemstack:get_name()]._infinity_name

	if dura <= 16 then
		itemstack:replace(name .. "_" .. (itemstack:get_name():sub(name:len() + 2) - 1))
		return itemstack
	else
		local max_uses = math.floor(dura / 16)
		local meta = itemstack:get_meta()
		meta:set_int("uses", meta:get_int("uses", 0) + 1)

		if meta:get_int("uses", 0) >= max_uses then
			itemstack:replace(name .. "_" .. (itemstack:get_name():sub(name:len() + 2) - 1))
		end

		return itemstack
	end
end
local drone_refs = {}

-- Prevent 3d armor from messing up the model
local old_update_player_visuals = armor.update_player_visuals
armor.update_player_visuals = function(self, player)
	if drone_refs[player:get_player_name()] ~= nil then return end
	old_update_player_visuals(self, player)
end

-- Prevents players from dropping drone control items
local old_item_drop = minetest.item_drop
function minetest.item_drop(itemstack, dropper, pos)
	if drone_refs[dropper:get_player_name()] ~= nil then return itemstack end
	return old_item_drop(itemstack, dropper, pos)
end

-- Functions to convert the player into the drone, and back again
local function enter_drone(name)
	local player = minetest.get_player_by_name(name)
	if not player then return end

	if drone_refs[name] ~= nil then return end

	drone_refs[name] = {
		collision = table.copy(player:get_properties().collisionbox),
		textures = table.copy(player:get_properties().textures),
		mesh = player:get_properties().mesh,
		eye_offset_first = player:get_eye_offset().offset_first,
		eye_offset_third = player:get_eye_offset().offset_third,
		vertical = player:get_look_vertical(),
		horizontal = player:get_look_horizontal(),
		inventory = player:get_inventory():get_lists(),
		formspec = player:get_inventory_formspec(),
		hotbar = player:hud_get_hotbar_itemcount(),
		hud = player:hud_add({hud_elem_type = "image", text = "infinity_ui_drone_overlay.png", position = {x = 0.5, y = 0.5}, scale = {x = -100, y = -100}}),
		ent = minetest.add_entity(player:get_pos(), "infinity:drone_player_ref", minetest.serialize({player = name})):get_luaentity()
	}

	minetest.sound_play("infinity_drone_enter", {to_player = name}, true)

	player:set_properties({ 
    collisionbox = {-0.4, 0, -0.4, 0.4, 0.45, 0.4},
    visual_size = {x = 0.63, y = 0.63, z = 0.63},
    mesh = "character.b3d",
    textures = {"infinity_vision.png"},
	})
	player:set_nametag_attributes({text = "Vision"})
	player:set_eye_offset({ x = 0, y = -5, z = 0 }, player:get_eye_offset().offset_third)
	player:set_physics_override({ speed = 4, jump = 2, gravity = 1, sneak = true })
	player:hud_set_hotbar_itemcount(2)
	player:hud_set_flags({healthbar = false, breathbar = false, hotbar = false})
	player:set_inventory_formspec([[
		size[4, 2]
		real_coordinates[true]
		button[1,0.6;2,0.75;infinity_detonate_drone;Detonate]
	]])

	minetest.after(0, function()
		for list in pairs(player:get_inventory():get_lists()) do
			player:get_inventory():set_list(list, {})

			player:get_inventory():set_stack("main", 2, "infinity:drone_icon_detonate")

			while player:get_inventory():room_for_item('main', 'infinity:drone_icon_interact') do
				player:get_inventory():add_item("main", "infinity:drone_icon_interact")
			end
		end
	end)
end

local function exit_drone(name)
	local player = minetest.get_player_by_name(name)
	if not player then return end

	if not drone_refs[name] then return end
	local props = drone_refs[name]

	local exploder = minetest.add_entity(player:get_pos(), "infinity:drone_exploding", minetest.serialize({player = name}))

	minetest.sound_play("infinity_drone_exit", {to_player = name}, true)

	player:get_inventory():set_lists(props.inventory)
	player:set_inventory_formspec(props.formspec)
	player:set_properties({visual_size = {x = 0, y = 0}})	
	player:set_pos(props.ent.object:get_pos())
	player:set_eye_offset(props.eye_offset_first, props.eye_offset_third)
	player:set_physics_override({ speed = 1, jump = 1, gravity = 1, sneak = true })
	player:set_look_vertical(props.vertical)
	player:set_look_horizontal(props.horizontal)
	player:hud_set_flags({healthbar = true, breathbar = true, hotbar = true})
	player:hud_set_hotbar_itemcount(props.hotbar)
	player:hud_remove(props.hud)

	player:set_properties({ 
		collisionbox = props.collision,
    mesh = props.mesh,
    textures = props.textures,
	})

	minetest.after(0.6, function()
		props.ent.object:remove()

		if drone_refs[name] == props then
			drone_refs[name] = nil
		else return end

		player:set_nametag_attributes({text = player:get_player_name()})
		player:set_properties({ visual_size = {x = 1, y = 1} })
	end)


end

local function interact_remote(itemstack, player, pointed_thing)
	local name = player:get_player_name()
	local charge = itemstack:get_name():sub(26)

	if not drone_refs[name] then minetest.after(0, function() enter_drone(name) end) end
end

local function interact_remote_dead(itemstack, player, pointed_thing)
	local name = player:get_player_name()

end

minetest.register_on_player_receive_fields(function(player, _, fields)
  if fields.infinity_detonate_drone then
  	exit_drone(player:get_player_name())
  	minetest.close_formspec(player:get_player_name(), "")
  end
end)

minetest.register_on_shutdown(function()
	for p,_ in pairs(drone_refs) do
		exit_drone(p)
	end
end)

minetest.register_on_leaveplayer(function(player)
	exit_drone(player:get_player_name())
end)
minetest.register_on_player_hpchange(function(player, hp_change, reason)
	if drone_refs[player:get_player_name()] ~= nil then
		exit_drone(player:get_player_name())
		return 0
	else return hp_change end
end, true)


infinity.register_tool_3d("infinity:vision_summon", {
	description = "Summon Vision...",
	description = "Summon Vision...",
	tiles = { "infinity_visionwield.png" },
	-- groups = {not_in_creative_inventory = 1},
	inventory_image = "infinity_visioninventory.png",
	mesh = "character.b3d",
}, interact_remote, 100000000000000000000, true, interact_remote_dead)



minetest.register_entity("infinity:drone_player_ref", {
	initial_properties = {
    mesh = "character.b3d",
    visual = "mesh",
    collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
    stepheight = 1,
    light_source = 100,
    physical = true,
    collide_with_objects = false,
	},
	on_activate = function(self, static)
		local static = minetest.deserialize(static) or {}

		if not static.player then self.object:remove() return end

		self.player = static.player
		local player = minetest.get_player_by_name(self.player)

		if not player then self.object:remove() return end

		self.object:set_properties({ 
			textures = player:get_properties().textures,
			nametag = self.player
		})
		self.object:set_armor_groups({ immortal = 1 })
		self.object:set_yaw(player:get_look_horizontal())
	end,
	get_staticdata = function(self)
		return ""
	end,
	on_punch = function(self)
		minetest.after(0, function() exit_drone(self.player) end)
		self.object:remove()
	end,
	on_step = function(self, delta)
		self.object:set_velocity(vector.new())
	end,
})
minetest.register_entity("infinity:drone_exploding", {
	initial_properties = {
    mesh = "character.b3d",
    textures = {"infinity_vision.png"},
    collisionbox = {-0.4, 0, -0.4, 0.4, 0.45, 0.4},
    visual_size = {x = 0.63, y = 0.63, z = 0.63},
    visual = "mesh",
    stepheight = 1,
    physical = true,
    collide_with_objects = false,
    backface_culling = false,
	},

	on_activate = function(self, static)
		local static = minetest.deserialize(static) or {}
		if not static.player then self.object:remove() return end

		local player = minetest.get_player_by_name(static.player)
		if not player then self.object:remove() return end

		self.object:set_yaw(player:get_look_horizontal())
		self.life = 0

		self.object:set_velocity(vector.new(0, -10, 0))
		self.object:set_hp(10)
	end,

	on_step = function (self, delta)
		self.life = self.life + delta;

		local texture = "infinity_vision.png"
		if self.life * 40 % 20 > 10 and self.life * 40 % 20 < 20 then texture = "infinity_vision.png^[colorize:#ffcccc:120" end

		self.object:set_properties({ textures = { texture } })

		if self.life > 3 then
			if minetest.registered_nodes["tnt:tnt"] ~= nil then
				tnt.boom(self.object:get_pos(), {radius = 7.5})
			end
			self.object:remove()
		end
	end
})

infinity.register_tool_3d("infinity:drone_icon_interact", {
	description = "Almost as Strong as the Infinity Gauntlet...",
	tiles = { "infinity_entity_remote_drone.png" },
	mesh = "infinity_tool_drone_turret.b3d",
	range = 100,  	
tool_capabilities = {
        full_punch_interval = 0.001,
        max_drop_level = 1,
        groupcaps = {
           choppy = {times = {[1]=1.00, [2]=0.50, [3]=0.75},uses = 10000000000000000000000000000000000, maxlevel = 5},
      cracky={times = {[1]=1.00, [2]=0.50, [3]=0.75},uses = 10000000000000000000000000000000000, maxlevel = 5},
      crumbly = {times = {[1]=1.00, [2]=0.50, [3]=0.75},uses = 10000000000000000000000000000000000, maxlevel = 5},
      snappy = {times = {[1]=1.00, [2]=0.50, [3]=0.75},uses = 10000000000000000000000000000000000, maxlevel = 5},
      oddly_breakable_by_hand = {times = {[1]=1.00, [2]=0.50, [3]=0.75},uses = 10000000000000000000000000000000000, maxlevel = 5},
      pickaxey = {times = {[1]=1.00, [2]=0.50, [3]=0.75},uses = 10000000000000000000000000000000000, maxlevel = 5},
      axey={times = {[1]=1.00, [2]=0.50, [3]=0.75},uses = 10000000000000000000000000000000000, maxlevel = 5},
      shovely={times = {[1]=1.00, [2]=0.50, [3]=0.75},uses = 10000000000000000000000000000000000, maxlevel = 5},
      pickaxey_dig_iron = {times={[1]=1.00, [2]=0.50, [3]=0.75},uses = 10000000000000000000000000000000000, maxlevel = 5},
        },
        damage_groups = { fleshy = RCB },
 },
	groups = {not_in_creative_inventory = 1},
		on_place = function(itemstack, placer, pointed_thing)
	
end
}, function(_, player)
	minetest.sound_play("infinity_interact", {pos = pos, max_hear_distance = 32}, true)
	
end)

infinity.register_tool_3d("infinity:drone_icon_detonate", {
	description = "Detonate",

	tiles = { "infinity_entity_remote_drone.png" },
	mesh = "infinity_tool_remote_drone_detonate.b3d",
	on_place = function()
	end,
	range = 0,
	groups = {not_in_creative_inventory = 1},
}, function(_, placer) minetest.after(0, function() exit_drone(placer:get_player_name()) end) end)

local t = 0
minetest.register_globalstep(function(delta)
	t = t + delta
	if t < 0.1 then return end
	t = t - 0.1

	for p,_ in pairs(drone_refs) do
		local player = minetest.get_player_by_name(p)

		if vector.length(player:get_player_velocity()) > 0 then
			local texture = player:get_properties().textures[1]
			if texture == "infinity_vision.png" then texture = "infinity_vision_1.png"
			else texture = "infinity_vision.png" end

			player:set_properties({textures = {texture}})
		end
	end
end)

dofile(minetest.get_modpath("infinity") .. "/soulworld.lua")

dofile(minetest.get_modpath("infinity") .. "/crafting.lua")

dofile(minetest.get_modpath("infinity") .. "/door.lua")

if minetest.get_modpath("1myfavs") then

dofile(minetest.get_modpath("infinity") .. "/fakes.lua")
end