mirror of
https://github.com/minetest/minetest.git
synced 2024-08-18 20:44:16 +02:00
Add support for attached facedir/4dir nodes (#11432)
This commit is contained in:
parent
1c10988d6a
commit
3c7f26d937
@ -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
|
||||
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 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
|
||||
-- The fallback vector here is in case 'wallmounted 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.
|
||||
-- The fallback vector corresponds to param2 = 0.
|
||||
-- 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user