hades_revisited/mods/hades_beds/functions.lua

98 lines
2.9 KiB
Lua

local S = minetest.get_translator("hades_beds")
-- helper functions
function hades_beds.on_rightclick(pos, player)
hades_beds.set_spawn(player, pos)
end
-- Returns true if players can spawn into the given node safely.
local function node_is_spawnable_in(node, is_upper)
-- All non-walkable, non-damaging, non-drowning nodes are safe.
-- Also the bed as a special case for the lower check.
if not node then
return false
end
if not is_upper and minetest.get_item_group(node.name, "bed") ~= 0 then
return true
end
local def = minetest.registered_nodes[node.name]
if not def.walkable and def.drowning <= 0 and def.damage_per_second <= 0 then
return true
end
return false
end
-- Returns true if players can spawn on given node safely (without falling).
local function node_is_spawnable_on(node)
-- All walkable full cube nodes that don't disable jump are accepted
if not node then
return false
end
local def = minetest.registered_nodes[node.name]
if def.walkable and
((def.collision_box == nil and def.node_box == nil) or
(not def.collision_box and def.node_box and def.node_box.type == "regular") or
(not def.node_box and def.collision_box and def.collision_box.type == "regular")) and
(minetest.get_item_group(node.name, "disable_jump") == 0) then
return true
end
return false
end
-- callbacks
local attempt_bed_respawn = function(player)
-- Place player on respawn position if set
local name = player:get_player_name()
local pos = hades_beds.get_spawn(player)
if pos then
local check_posses = {
{ x=0, y=0, z=0 },
{ x=0, y=0, z=-1 },
{ x=0, y=0, z=1 },
{ x=-1, y=0, z=0 },
{ x=1, y=0, z=0 },
{ x=-1, y=0, z=-1 },
{ x=-1, y=0, z=1 },
{ x=1, y=0, z=-1 },
{ x=1, y=0, z=1 },
}
-- Check if position is safe, if not, try to spawn to one of the
-- neighbor blocks
for n=1, #check_posses do
local cpos = vector.add(pos, check_posses[n])
local node = minetest.get_node(cpos)
if node_is_spawnable_in(node, false) then
local is_bed = minetest.get_item_group(node.name, "bed") ~= 0
-- Check posses above (must be free)
-- and below (must be walkable)
local acpos = { x=cpos.x, y=cpos.y+1, z=cpos.z }
local abpos = { x=cpos.x, y=cpos.y-1, z=cpos.z }
local anode = minetest.get_node(acpos)
local bnode = minetest.get_node(abpos)
if node_is_spawnable_in(anode, true) and ((n == 1 and is_bed) or node_is_spawnable_on(bnode)) then
local spos = cpos
if not is_bed then
spos.y = spos.y - 0.5
end
player:set_pos(spos)
return true
end
end
end
hades_beds.unset_spawn(player)
minetest.chat_send_player(name, minetest.colorize("#FFFF00", S("Your respawn position was blocked or dangerous. You've lost your old respawn position.")))
return false
end
return false
end
minetest.register_on_respawnplayer(attempt_bed_respawn)
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
hades_beds.player[name] = nil
end)