2021-05-29 16:12:33 +02:00
|
|
|
local S = minetest.get_translator(minetest.get_current_modname())
|
2017-02-12 23:43:30 +01:00
|
|
|
|
2021-04-20 22:36:07 +02:00
|
|
|
local minetest_get_node = minetest.get_node
|
|
|
|
local minetest_get_node_or_nil = minetest.get_node_or_nil
|
|
|
|
local minetest_remove_node = minetest.remove_node
|
|
|
|
local minetest_facedir_to_dir = minetest.facedir_to_dir
|
|
|
|
local vector_add = vector.add
|
|
|
|
local vector_subtract = vector.subtract
|
|
|
|
|
|
|
|
local function get_bed_next_node(pos, node)
|
|
|
|
local node = node or minetest_get_node_or_nil(pos)
|
2021-01-16 19:50:29 +01:00
|
|
|
if not node then return end
|
2021-04-20 22:36:07 +02:00
|
|
|
|
|
|
|
local dir = minetest_facedir_to_dir(node.param2)
|
|
|
|
|
|
|
|
local pos2, bottom
|
2021-01-16 19:50:29 +01:00
|
|
|
if string.sub(node.name, -4) == "_top" then
|
2021-04-20 22:36:07 +02:00
|
|
|
pos2 = vector_subtract(pos, dir)
|
|
|
|
else
|
|
|
|
pos2 = vector_add(pos, dir)
|
|
|
|
bottom = true
|
|
|
|
end
|
|
|
|
|
|
|
|
local node2 = minetest_get_node(pos2)
|
|
|
|
return pos2, node2, bottom, dir
|
|
|
|
end
|
|
|
|
|
|
|
|
local function rotate(pos, node, user, mode, new_param2)
|
|
|
|
if mode ~= screwdriver.ROTATE_FACE then
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
local p, node2, bottom = get_bed_next_node(pos, node)
|
|
|
|
if not node2 then return end
|
|
|
|
|
|
|
|
local name = node2.name
|
|
|
|
if not minetest.get_item_group(name, "bed") == 2 or not node.param2 == node2.param2 then return false end
|
|
|
|
|
|
|
|
if bottom then
|
|
|
|
name = string.sub(name, 1, -5)
|
|
|
|
else
|
|
|
|
name = string.sub(name, 1, -8)
|
|
|
|
end
|
|
|
|
|
|
|
|
if minetest.is_protected(p, user:get_player_name()) then
|
|
|
|
minetest.record_protection_violation(p, user:get_player_name())
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
2021-05-23 01:09:45 +02:00
|
|
|
local newp
|
|
|
|
local new_dir = minetest_facedir_to_dir(new_param2)
|
|
|
|
|
2021-04-20 22:36:07 +02:00
|
|
|
if bottom then
|
|
|
|
newp = vector_add(pos, new_dir)
|
|
|
|
else
|
|
|
|
newp = vector_subtract(pos, new_dir)
|
|
|
|
end
|
|
|
|
|
|
|
|
local node3 = minetest_get_node_or_nil(newp)
|
|
|
|
if not node3 then return false end
|
|
|
|
|
|
|
|
local node_def = minetest.registered_nodes[node3.name]
|
|
|
|
if not node_def or not node_def.buildable_to then return false end
|
|
|
|
|
|
|
|
if minetest.is_protected(newp, user:get_player_name()) then
|
|
|
|
minetest.record_protection_violation(newp, user:get_player_name())
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
node.param2 = new_param2
|
|
|
|
-- do not remove_node here - it will trigger destroy_bed()
|
|
|
|
minetest.swap_node(p, {name = "air"})
|
|
|
|
minetest.swap_node(pos, node)
|
|
|
|
minetest.swap_node(newp, {name = name .. (bottom and "_top" or "_bottom"), param2 = new_param2})
|
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2024-04-27 09:17:24 +02:00
|
|
|
local creative_dig = {}
|
2021-04-20 22:36:07 +02:00
|
|
|
local function destruct_bed(pos, oldnode)
|
|
|
|
local node = oldnode or minetest_get_node_or_nil(pos)
|
|
|
|
if not node then return end
|
|
|
|
|
|
|
|
local pos2, node2, bottom = get_bed_next_node(pos, oldnode)
|
|
|
|
|
2024-04-27 09:17:24 +02:00
|
|
|
-- Check creative dig flags and don't drop an item if the bed was dug by a player in
|
|
|
|
-- creative mode
|
|
|
|
local pos_hash = minetest.hash_node_position(pos)
|
|
|
|
local pos2_hash = minetest.hash_node_position(pos2)
|
|
|
|
local creative_mode = creative_dig[pos_hash] or creative_dig[pos2_hash]
|
|
|
|
|
2021-04-20 22:36:07 +02:00
|
|
|
if bottom then
|
2021-01-16 19:50:29 +01:00
|
|
|
if node2 and string.sub(node2.name, -4) == "_top" then
|
2021-04-20 22:36:07 +02:00
|
|
|
minetest_remove_node(pos2)
|
|
|
|
end
|
2024-04-20 11:43:48 +02:00
|
|
|
|
2024-04-27 09:17:24 +02:00
|
|
|
-- Drop the bed only when removing the top to prevent duplication and only if
|
|
|
|
-- it wasn't dug by a player in creative mode
|
2024-04-20 11:43:48 +02:00
|
|
|
local bed_node_def = minetest.registered_nodes[node.name]
|
2024-04-27 09:17:24 +02:00
|
|
|
if bed_node_def and bed_node_def._mcl_beds_drop and not creative_mode then
|
2024-04-20 11:43:48 +02:00
|
|
|
local stack = ItemStack(bed_node_def._mcl_beds_drop)
|
|
|
|
minetest.add_item(pos2, stack)
|
|
|
|
end
|
2021-04-20 22:36:07 +02:00
|
|
|
else
|
|
|
|
if node2 and string.sub(node2.name, -7) == "_bottom" then
|
|
|
|
minetest_remove_node(pos2)
|
2021-01-16 19:50:29 +01:00
|
|
|
end
|
2017-02-12 23:43:30 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-04-27 09:17:24 +02:00
|
|
|
local function dig_bed(pos, node, digger)
|
|
|
|
local pos_hash = minetest.hash_node_position(pos)
|
|
|
|
|
|
|
|
if digger then
|
|
|
|
local name = digger:get_player_name()
|
|
|
|
if minetest.is_protected(pos, name) then
|
|
|
|
minetest.record_protection_violation(pos, name)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Set creative dig flags to stop dropping items
|
|
|
|
if minetest.is_creative_enabled(name) then
|
|
|
|
creative_dig[pos_hash] = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Trigger the destruct_bed function
|
|
|
|
minetest.remove_node(pos)
|
|
|
|
|
|
|
|
-- Clean up creative dig flag
|
|
|
|
creative_dig[pos_hash] = nil
|
|
|
|
end
|
|
|
|
|
2019-02-20 20:52:06 +01:00
|
|
|
local function kick_player_after_destruct(destruct_pos)
|
|
|
|
for name, player_bed_pos in pairs(mcl_beds.bed_pos) do
|
|
|
|
if vector.distance(destruct_pos, player_bed_pos) < 0.1 then
|
2019-02-20 18:01:21 +01:00
|
|
|
local player = minetest.get_player_by_name(name)
|
|
|
|
if player and player:is_player() then
|
|
|
|
mcl_beds.kick_player(player)
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-07-26 19:07:57 +02:00
|
|
|
local default_sounds
|
|
|
|
if minetest.get_modpath("mcl_sounds") then
|
2019-06-14 23:03:12 +02:00
|
|
|
default_sounds = mcl_sounds.node_sound_wood_defaults({
|
2022-12-20 21:08:59 +01:00
|
|
|
footstep = mcl_sounds.node_sound_wool_defaults().footstep,
|
2019-06-14 23:03:12 +02:00
|
|
|
})
|
2017-07-26 19:07:57 +02:00
|
|
|
end
|
|
|
|
|
2024-04-20 13:03:06 +02:00
|
|
|
local function place_bed(name, placer, pos, dir)
|
|
|
|
local botpos = vector_add(pos, minetest_facedir_to_dir(dir))
|
|
|
|
|
|
|
|
if minetest.is_protected(botpos, placer:get_player_name()) and
|
|
|
|
not minetest.check_player_privs(placer, "protection_bypass") then
|
|
|
|
minetest.record_protection_violation(botpos, placer:get_player_name())
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
local botdef = minetest.registered_nodes[minetest_get_node(botpos).name]
|
|
|
|
if not botdef or not botdef.buildable_to then
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
minetest.set_node(pos, {name = name .. "_bottom", param2 = dir})
|
|
|
|
minetest.set_node(botpos, {name = name .. "_top", param2 = dir})
|
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2017-05-07 20:21:37 +02:00
|
|
|
function mcl_beds.register_bed(name, def)
|
2022-10-06 18:36:51 +02:00
|
|
|
local common_box = {
|
|
|
|
type = "fixed",
|
|
|
|
fixed = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5},
|
|
|
|
}
|
2024-06-08 02:05:39 +02:00
|
|
|
|
2017-02-12 23:43:30 +01:00
|
|
|
minetest.register_node(name .. "_bottom", {
|
|
|
|
description = def.description,
|
|
|
|
inventory_image = def.inventory_image,
|
|
|
|
wield_image = def.wield_image,
|
2022-10-06 18:36:51 +02:00
|
|
|
drawtype = "mesh",
|
|
|
|
mesh = "mcl_beds_bed_bottom.obj",
|
|
|
|
tiles = def.tiles,
|
2021-02-18 14:00:17 +01:00
|
|
|
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
|
2017-02-12 23:43:30 +01:00
|
|
|
paramtype = "light",
|
|
|
|
paramtype2 = "facedir",
|
|
|
|
is_ground_content = false,
|
|
|
|
stack_max = 1,
|
2021-05-23 01:09:45 +02:00
|
|
|
groups = {handy=1, bed = 1, dig_by_piston=1, bouncy=66, fall_damage_add_percent=-50, deco_block = 1, flammable=-1},
|
2017-02-27 00:51:50 +01:00
|
|
|
_mcl_hardness = 0.2,
|
2017-03-20 18:38:58 +01:00
|
|
|
_mcl_blast_resistance = 1,
|
2017-07-26 19:07:57 +02:00
|
|
|
sounds = def.sounds or default_sounds,
|
2022-10-06 18:36:51 +02:00
|
|
|
selection_box = common_box,
|
|
|
|
collision_box = common_box,
|
2024-04-20 11:43:48 +02:00
|
|
|
_mcl_beds_drop = def.recipe and name or "",
|
|
|
|
drop = "",
|
2021-03-29 18:13:10 +02:00
|
|
|
node_placement_prediction = "",
|
2024-06-08 02:05:39 +02:00
|
|
|
|
2017-02-12 23:43:30 +01:00
|
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
|
|
local under = pointed_thing.under
|
2017-03-02 16:20:19 +01:00
|
|
|
|
|
|
|
-- Use pointed node's on_rightclick function first, if present
|
2021-04-20 22:36:07 +02:00
|
|
|
local node = minetest_get_node(under)
|
2017-03-02 16:20:19 +01:00
|
|
|
if placer and not placer:get_player_control().sneak then
|
|
|
|
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
|
|
|
|
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-02-12 23:43:30 +01:00
|
|
|
local pos
|
2021-04-20 22:36:07 +02:00
|
|
|
local undername = minetest_get_node(under).name
|
2017-06-29 13:02:53 +02:00
|
|
|
if minetest.registered_items[undername] and minetest.registered_items[undername].buildable_to then
|
2017-02-12 23:43:30 +01:00
|
|
|
pos = under
|
|
|
|
else
|
|
|
|
pos = pointed_thing.above
|
|
|
|
end
|
|
|
|
|
|
|
|
if minetest.is_protected(pos, placer:get_player_name()) and
|
|
|
|
not minetest.check_player_privs(placer, "protection_bypass") then
|
|
|
|
minetest.record_protection_violation(pos, placer:get_player_name())
|
|
|
|
return itemstack
|
|
|
|
end
|
|
|
|
|
2021-04-20 22:36:07 +02:00
|
|
|
local node_def = minetest.registered_nodes[minetest_get_node(pos).name]
|
2017-02-12 23:43:30 +01:00
|
|
|
if not node_def or not node_def.buildable_to then
|
|
|
|
return itemstack
|
|
|
|
end
|
|
|
|
|
2024-04-20 13:03:06 +02:00
|
|
|
-- Try to place in three directions: inline with the view and rotated to
|
|
|
|
-- the right and left
|
2017-02-12 23:43:30 +01:00
|
|
|
local dir = minetest.dir_to_facedir(placer:get_look_dir())
|
2024-04-20 13:03:06 +02:00
|
|
|
if place_bed(name, placer, pos, dir) or
|
|
|
|
place_bed(name, placer, pos, (dir+1)%4) or
|
|
|
|
place_bed(name, placer, pos, (dir+3)%4) or
|
|
|
|
place_bed(name, placer, pos, (dir+2)%4) then
|
|
|
|
-- Bed was places
|
|
|
|
if not minetest.is_creative_enabled(placer:get_player_name()) then
|
|
|
|
itemstack:take_item()
|
|
|
|
end
|
2017-02-12 23:43:30 +01:00
|
|
|
end
|
|
|
|
return itemstack
|
|
|
|
end,
|
|
|
|
|
2021-01-16 19:50:29 +01:00
|
|
|
after_destruct = destruct_bed,
|
2024-04-27 09:17:24 +02:00
|
|
|
on_dig = dig_bed,
|
2017-02-12 23:43:30 +01:00
|
|
|
|
2021-01-19 22:46:52 +01:00
|
|
|
on_destruct = kick_player_after_destruct,
|
|
|
|
|
2017-02-12 23:43:30 +01:00
|
|
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
2019-02-20 19:22:24 +01:00
|
|
|
mcl_beds.on_rightclick(pos, clicker, false)
|
2017-02-12 23:43:30 +01:00
|
|
|
return itemstack
|
|
|
|
end,
|
|
|
|
|
2021-04-20 22:36:07 +02:00
|
|
|
on_rotate = rotate,
|
2017-02-12 23:43:30 +01:00
|
|
|
})
|
|
|
|
|
2024-06-08 02:05:39 +02:00
|
|
|
|
2017-05-09 19:02:24 +02:00
|
|
|
|
2017-02-12 23:43:30 +01:00
|
|
|
minetest.register_node(name .. "_top", {
|
2022-10-06 18:36:51 +02:00
|
|
|
drawtype = "mesh",
|
|
|
|
mesh = "mcl_beds_bed_top.obj",
|
|
|
|
tiles = def.tiles,
|
2021-02-18 14:00:17 +01:00
|
|
|
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
|
2017-02-12 23:43:30 +01:00
|
|
|
paramtype = "light",
|
|
|
|
paramtype2 = "facedir",
|
|
|
|
is_ground_content = false,
|
2017-05-09 19:12:35 +02:00
|
|
|
-- FIXME: Should be bouncy=66, but this would be a higher bounciness than slime blocks!
|
2022-02-15 02:53:23 +01:00
|
|
|
groups = {handy = 1, flammable = -1, bed = 2, dig_by_piston=1, bouncy=33, fall_damage_add_percent=-50, not_in_creative_inventory = 1},
|
2017-02-27 00:51:50 +01:00
|
|
|
_mcl_hardness = 0.2,
|
2017-03-20 18:38:58 +01:00
|
|
|
_mcl_blast_resistance = 1,
|
2017-07-26 19:07:57 +02:00
|
|
|
sounds = def.sounds or default_sounds,
|
2024-04-20 11:43:48 +02:00
|
|
|
drop = "",
|
2022-10-06 18:36:51 +02:00
|
|
|
selection_box = common_box,
|
|
|
|
collision_box = common_box,
|
2024-06-08 02:05:39 +02:00
|
|
|
|
2017-05-09 18:52:40 +02:00
|
|
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
2019-02-20 19:22:24 +01:00
|
|
|
mcl_beds.on_rightclick(pos, clicker, true)
|
2017-05-09 18:52:40 +02:00
|
|
|
return itemstack
|
|
|
|
end,
|
2022-10-06 18:36:51 +02:00
|
|
|
|
2021-04-20 22:36:07 +02:00
|
|
|
on_rotate = rotate,
|
2021-01-16 19:50:29 +01:00
|
|
|
after_destruct = destruct_bed,
|
2024-04-27 09:17:24 +02:00
|
|
|
on_dig = dig_bed,
|
2017-02-12 23:43:30 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
minetest.register_alias(name, name .. "_bottom")
|
|
|
|
|
2017-07-26 19:07:57 +02:00
|
|
|
if def.recipe then
|
|
|
|
minetest.register_craft({
|
|
|
|
output = name,
|
|
|
|
recipe = def.recipe
|
|
|
|
})
|
|
|
|
end
|
2017-05-09 18:52:40 +02:00
|
|
|
|
|
|
|
doc.add_entry_alias("nodes", name.."_bottom", "nodes", name.."_top")
|
2017-02-12 23:43:30 +01:00
|
|
|
end
|
2017-11-24 07:04:03 +01:00
|
|
|
|
|
|
|
|