2021-07-09 12:24:14 -07:00
local S = minetest.get_translator ( " hades_beds " )
2015-11-12 11:09:26 -08:00
-- helper functions
2021-07-03 07:07:43 -07:00
function hades_beds . on_rightclick ( pos , player )
hades_beds.set_spawn ( player , pos )
2015-11-12 11:09:26 -08:00
end
2021-07-09 12:24:14 -07:00
-- 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
2015-11-12 11:09:26 -08:00
-- callbacks
2021-07-09 12:24:14 -07:00
local attempt_bed_respawn = function ( player )
-- Place player on respawn position if set
2015-11-12 11:09:26 -08:00
local name = player : get_player_name ( )
2021-07-03 07:07:43 -07:00
local pos = hades_beds.get_spawn ( player )
2015-11-12 11:09:26 -08:00
if pos then
2021-07-09 12:24:14 -07:00
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
2015-11-12 11:09:26 -08:00
end
2021-07-09 12:24:14 -07:00
return false
end
minetest.register_on_respawnplayer ( attempt_bed_respawn )
2015-11-12 11:09:26 -08:00
minetest.register_on_leaveplayer ( function ( player )
2018-01-07 09:18:58 -08:00
local name = player : get_player_name ( )
2021-07-03 07:07:43 -07:00
hades_beds.player [ name ] = nil
2015-11-12 11:09:26 -08:00
end )