-- Beacon model stolen from Farlands.
-- Texture and model license: same as original (LGPL for code [model], CC-BY-SA 3.9 Unported for texture)-- This code: Copyright 2020 by Astrobe, LGPL license.


local st=minetest.get_mod_storage()

local playersp={}

local function update_sp(player, pos)
	local name=player:get_player_name()
	if not name then return end
	if playersp[name] then
		player:hud_remove(playersp[name])
	end

	local id=player:hud_add {
		type="waypoint",
		name="X",
		precision=1,
		world_pos=pos }
	playersp[name]=id
end

local function move_to_spawn(entity, reason)
	local name=entity:get_player_name()
	mobs.tp_fx(entity:get_pos())
	local p=minetest.deserialize(st:get_string(name)) or minetest.deserialize(st:get_string("singleplayer"))
	-- if neither the player nor singleplayer have a spawning point, this a new world. So create a beacon.
	if not p then
		p= entity:get_pos()
		minetest.set_node(p, {name="beacon:beacon"})
		st:set_string(name, minetest.serialize(p))
		st:set_string("singleplayer", minetest.serialize(p))
		update_sp(entity, p)
		-- in some pathological cases, the spot chosen by the engine is right under something,
		-- so we have to clear the position.
		p.y=p.y+1
		minetest.set_node(p, {name="air"})
		p.y=p.y-1
	end
	entity:set_pos({x=p.x, y=p.y+1, z=p.z})
	--minetest.log("Moving "..name.." to beacon")
	return true
end

local function player_home(name)
	return minetest.deserialize(st:get_string(name)) or {x=0, y=0, z=0}
end

beacon={ recall=move_to_spawn, home=player_home}

minetest.register_on_respawnplayer(function(entity, reason)
	local name=entity:get_player_name()
	if not name then return end 
	minetest.chat_send_all("Emergency recall: "..name)
	return move_to_spawn(entity, reason)
end
)
minetest.register_on_newplayer(move_to_spawn)



minetest.register_on_joinplayer(function(player)
	local p=minetest.deserialize(st:get_string(player:get_player_name())) or minetest.deserialize(st:get_string("singleplayer"))
	if p then update_sp(player, p) end
	end)

minetest.register_node("beacon:beacon", {
	description = "Beacon. Feed:\nGreen mese crystal to set home\nGrey mese shard to teleport to home.\nGet: from traders, for a Mese block.",
	tiles = {
		{name="mobs_beacon.png^[noalpha", backface_culling=false}
	},
	drawtype = "glasslike",
	paramtype = "light",
	light_source= 8,
	-- use_texture_alpha = "blend",
	groups = {cracky=3, protected=1, nopicker=1 },
	sounds = default.node_sound_glass_defaults(),

	on_rightclick=function(pos, node, player, obj)
		if player==nil then return false end
		local name=player:get_player_name()
		if not mf.clan_ok(name, pos) then return false end
		local offer=obj:get_name()
		if offer=="more_mese:mese_crystal_green" then
			st:set_string(name, minetest.serialize(pos))
			update_sp(player, pos)
			minetest.chat_send_player(name, "Respawn point set")
		elseif offer=="more_mese:mese_crystal_fragment_grey" or (offer=="default:mese_crystal_fragment" and mf.is_keymaster(name)) then
			move_to_spawn(player)
			minetest.sound_play("nether_portal_teleport", {max_hear_distance=16}, true)
		else return false end
		obj:take_item()
		return false
	end,

	--[[
	on_key_use = function(pos, player, key)
		local itemstack = player:get_wielded_item()
		local key_meta = itemstack:get_meta()
		local name=player:get_player_name()
		local secret=key_meta:get_string("secret")

		if secret == "" then
			minetest.chat_send_player(name, "Key is blank !?")
			return
		end
		local p=minetest.deserialize(secret)
		if not p or not (p.x and p.y and p.z) then
			minetest.chat_send_player(name, "Not a beacon key?")
			return
		end
		if vector.distance(p, pos)<5 then
			minetest.chat_send_player(name, "Destination is too close")
			return
		end
		p.y=p.y+1
		player:set_pos(p)
		minetest.sound_play("nether_portal_teleport", {object=player, max_hear_distance=16})
		if not mf.is_keymaster(name) then key:clear() end
	end,

	--[[
	on_skeleton_key_use = function(pos, player, newsecret)
		local name = player:get_player_name()
		return minetest.serialize(pos), "a beacon", name 
	end,
	]]

})

minetest.register_chatcommand("recall", {
	description="Teleports a player to their home beacon. You can recall yourself. Costs 1 RP.",
	params="Name of the player to be recalled.",
	func=function(name, param)
		local player=minetest.get_player_by_name(param)
		if not player then
			minetest.chat_send_player(name, "Who?")
			return
		end
		if rp.get_player_count(name)<=1 then
			minetest.chat_send_player(name, "You don't have enough RP")
			return
		end
		rp.award(name, -1)
		move_to_spawn(player)
	end
})

