Add support for attached facedir/4dir nodes (#11432)

This commit is contained in:
Wuzzy 2022-11-24 23:56:07 +01:00 committed by GitHub
parent 1c10988d6a
commit 3c7f26d937
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 177 additions and 27 deletions

@ -466,15 +466,39 @@ local function drop_attached_node(p)
end
end
function builtin_shared.check_attached_node(p, n)
function builtin_shared.check_attached_node(p, n, group_rating)
local def = core.registered_nodes[n.name]
local d = vector.zero()
if def.paramtype2 == "wallmounted" or
def.paramtype2 == "colorwallmounted" then
-- The fallback vector here is in case 'wallmounted to dir' is nil due
if group_rating == 3 then
-- always attach to floor
d.y = -1
elseif group_rating == 4 then
-- always attach to ceiling
d.y = 1
elseif group_rating == 2 then
-- attach to facedir or 4dir direction
if (def.paramtype2 == "facedir" or
def.paramtype2 == "colorfacedir") then
-- Attach to whatever facedir is "mounted to".
-- For facedir, this is where tile no. 5 point at.
-- The fallback vector here is in case 'facedir to dir' is nil due
-- to voxelmanip placing a wallmounted node without resetting a
-- pre-existing param2 value that is out-of-range for wallmounted.
-- pre-existing param2 value that is out-of-range for facedir.
-- The fallback vector corresponds to param2 = 0.
d = core.facedir_to_dir(n.param2) or vector.new(0, 0, 1)
elseif (def.paramtype2 == "4dir" or
def.paramtype2 == "color4dir") then
-- Similar to facedir handling
d = core.fourdir_to_dir(n.param2) or vector.new(0, 0, 1)
end
elseif def.paramtype2 == "wallmounted" or
def.paramtype2 == "colorwallmounted" then
-- Attach to whatever this node is "mounted to".
-- This where tile no. 2 points at.
-- The fallback vector here is used for the same reason as
-- for facedir nodes.
d = core.wallmounted_to_dir(n.param2) or vector.new(0, 1, 0)
else
d.y = -1
@ -519,8 +543,9 @@ function core.check_single_for_falling(p)
end
end
if core.get_item_group(n.name, "attached_node") ~= 0 then
if not builtin_shared.check_attached_node(p, n) then
local an = core.get_item_group(n.name, "attached_node")
if an ~= 0 then
if not builtin_shared.check_attached_node(p, n, an) then
drop_attached_node(p)
return true
end

@ -240,8 +240,9 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
end
-- Check if the node is attached and if it can be placed there
if core.get_item_group(def.name, "attached_node") ~= 0 and
not builtin_shared.check_attached_node(place_to, newnode) then
local an = core.get_item_group(def.name, "attached_node")
if an ~= 0 and
not builtin_shared.check_attached_node(place_to, newnode, an) then
log("action", "attached node " .. def.name ..
" cannot be placed at " .. core.pos_to_string(place_to))
return itemstack, nil

@ -1890,9 +1890,16 @@ to games.
### Node-only groups
* `attached_node`: if the node under it is not a walkable block the node will be
dropped as an item. If the node is wallmounted the wallmounted direction is
checked.
* `attached_node`: the node is 'attached' to a neighboring node. It checks
whether the node it is attached to is walkable. If it
isn't, the node will drop as an item.
* `1`: if the node is wallmounted, the node is attached in the wallmounted
direction. Otherwise, the node is attached to the node below.
* `2`: if the node is facedir or 4dir, the facedir or 4dir direction is checked.
No effect for other nodes.
Note: The "attaching face" of this node is tile no. 5 (back face).
* `3`: the node is always attached to the node below.
* `4`: the node is always attached to the node above.
* `bouncy`: value is bounce speed in percent.
If positive, jump/sneak on floor impact will increase/decrease bounce height.
Negative value is the same bounciness, but non-controllable.

@ -57,7 +57,6 @@ minetest.register_node("testnodes:attached", {
},
groups = { attached_node = 1, dig_immediate = 3 },
})
-- This node attaches to the side of a node and drops as item
-- when the node it attaches to is gone.
minetest.register_node("testnodes:attached_wallmounted", {
@ -73,6 +72,61 @@ minetest.register_node("testnodes:attached_wallmounted", {
groups = { attached_node = 1, dig_immediate = 3 },
})
-- Wallmounted node that always attaches to the floor
minetest.register_node("testnodes:attached_wallmounted_floor", {
description = S("Floor-Attached Wallmounted Node"),
paramtype2 = "wallmounted",
tiles = {
"testnodes_attached_top.png",
"testnodes_attached_bottom.png",
"testnodes_attached_side.png",
},
groups = { attached_node = 3, dig_immediate = 3 },
color = "#FF8080",
})
-- This node attaches to the ceiling and drops as item
-- when the ceiling is gone.
minetest.register_node("testnodes:attached_top", {
description = S("Ceiling-Attached Node"),
tiles = {
"testnodes_attached_bottom.png",
"testnodes_attached_top.png",
"testnodes_attached_side.png^[transformR180",
},
groups = { attached_node = 4, dig_immediate = 3 },
})
-- Same as wallmounted attached, but for facedir
minetest.register_node("testnodes:attached_facedir", {
description = S("Facedir Attached Node"),
paramtype2 = "facedir",
tiles = {
"testnodes_attachedf_side.png^[transformR180",
"testnodes_attachedf_side.png",
"testnodes_attachedf_side.png^[transformR90",
"testnodes_attachedf_side.png^[transformR270",
"testnodes_attachedf_bottom.png",
"testnodes_attachedf_top.png",
},
groups = { attached_node = 2, dig_immediate = 3 },
})
-- Same as facedir attached, but for 4dir
minetest.register_node("testnodes:attached_4dir", {
description = S("4dir Attached Node"),
paramtype2 = "4dir",
tiles = {
"testnodes_attached4_side.png^[transformR180",
"testnodes_attached4_side.png",
"testnodes_attached4_side.png^[transformR90",
"testnodes_attached4_side.png^[transformR270",
"testnodes_attached4_bottom.png",
"testnodes_attached4_top.png",
},
groups = { attached_node = 2, dig_immediate = 3 },
})
-- Jump disabled
minetest.register_node("testnodes:nojump", {
description = S("Non-jumping Node").."\n"..

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

@ -3585,22 +3585,30 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
}
// Check attachment if node is in group attached_node
if (itemgroup_get(predicted_f.groups, "attached_node") != 0) {
const static v3s16 wallmounted_dirs[8] = {
v3s16(0, 1, 0),
v3s16(0, -1, 0),
v3s16(1, 0, 0),
v3s16(-1, 0, 0),
v3s16(0, 0, 1),
v3s16(0, 0, -1),
};
int an = itemgroup_get(predicted_f.groups, "attached_node");
if (an != 0) {
v3s16 pp;
if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)
pp = p + wallmounted_dirs[param2];
else
if (an == 3) {
pp = p + v3s16(0, -1, 0);
} else if (an == 4) {
pp = p + v3s16(0, 1, 0);
} else if (an == 2) {
if (predicted_f.param_type_2 == CPT2_FACEDIR ||
predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
pp = p + facedir_dirs[param2];
} else if (predicted_f.param_type_2 == CPT2_4DIR ||
predicted_f.param_type_2 == CPT2_COLORED_4DIR ) {
pp = p + fourdir_dirs[param2];
} else {
pp = p;
}
} else if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
pp = p + wallmounted_dirs[param2];
} else {
pp = p + v3s16(0, -1, 0);
}
if (!nodedef->get(map.getNode(pp)).walkable) {
soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;

@ -118,3 +118,52 @@ const u8 wallmounted_to_facedir[6] = {
8,
4 + 2
};
const v3s16 wallmounted_dirs[8] = {
v3s16(0, 1, 0),
v3s16(0, -1, 0),
v3s16(1, 0, 0),
v3s16(-1, 0, 0),
v3s16(0, 0, 1),
v3s16(0, 0, -1),
};
const v3s16 facedir_dirs[32] = {
//0
v3s16(0, 0, 1),
v3s16(1, 0, 0),
v3s16(0, 0, -1),
v3s16(-1, 0, 0),
//4
v3s16(0, -1, 0),
v3s16(1, 0, 0),
v3s16(0, 1, 0),
v3s16(-1, 0, 0),
//8
v3s16(0, 1, 0),
v3s16(1, 0, 0),
v3s16(0, -1, 0),
v3s16(-1, 0, 0),
//12
v3s16(0, 0, 1),
v3s16(0, -1, 0),
v3s16(0, 0, -1),
v3s16(0, 1, 0),
//16
v3s16(0, 0, 1),
v3s16(0, 1, 0),
v3s16(0, 0, -1),
v3s16(0, -1, 0),
//20
v3s16(0, 0, 1),
v3s16(-1, 0, 0),
v3s16(0, 0, -1),
v3s16(1, 0, 0),
};
const v3s16 fourdir_dirs[4] = {
v3s16(0, 0, 1),
v3s16(1, 0, 0),
v3s16(0, 0, -1),
v3s16(-1, 0, 0),
};

@ -33,6 +33,12 @@ extern const v3s16 g_27dirs[27];
extern const u8 wallmounted_to_facedir[6];
extern const v3s16 wallmounted_dirs[8];
extern const v3s16 facedir_dirs[32];
extern const v3s16 fourdir_dirs[4];
/// Direction in the 6D format. g_27dirs contains corresponding vectors.
/// Here P means Positive, N stands for Negative.
enum Direction6D {