mirror of
https://github.com/minetest/minetest.git
synced 2024-09-12 00:26:50 +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
|
||||||
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 def = core.registered_nodes[n.name]
|
||||||
local d = vector.zero()
|
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
|
def.paramtype2 == "colorwallmounted" then
|
||||||
-- The fallback vector here is in case 'wallmounted to dir' is nil due
|
-- Attach to whatever this node is "mounted to".
|
||||||
-- to voxelmanip placing a wallmounted node without resetting a
|
-- This where tile no. 2 points at.
|
||||||
-- pre-existing param2 value that is out-of-range for wallmounted.
|
|
||||||
-- The fallback vector corresponds to param2 = 0.
|
-- 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)
|
d = core.wallmounted_to_dir(n.param2) or vector.new(0, 1, 0)
|
||||||
else
|
else
|
||||||
d.y = -1
|
d.y = -1
|
||||||
@ -519,8 +543,9 @@ function core.check_single_for_falling(p)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if core.get_item_group(n.name, "attached_node") ~= 0 then
|
local an = core.get_item_group(n.name, "attached_node")
|
||||||
if not builtin_shared.check_attached_node(p, n) then
|
if an ~= 0 then
|
||||||
|
if not builtin_shared.check_attached_node(p, n, an) then
|
||||||
drop_attached_node(p)
|
drop_attached_node(p)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -240,8 +240,9 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Check if the node is attached and if it can be placed there
|
-- Check if the node is attached and if it can be placed there
|
||||||
if core.get_item_group(def.name, "attached_node") ~= 0 and
|
local an = core.get_item_group(def.name, "attached_node")
|
||||||
not builtin_shared.check_attached_node(place_to, newnode) then
|
if an ~= 0 and
|
||||||
|
not builtin_shared.check_attached_node(place_to, newnode, an) then
|
||||||
log("action", "attached node " .. def.name ..
|
log("action", "attached node " .. def.name ..
|
||||||
" cannot be placed at " .. core.pos_to_string(place_to))
|
" cannot be placed at " .. core.pos_to_string(place_to))
|
||||||
return itemstack, nil
|
return itemstack, nil
|
||||||
|
@ -1890,9 +1890,16 @@ to games.
|
|||||||
|
|
||||||
### Node-only groups
|
### Node-only groups
|
||||||
|
|
||||||
* `attached_node`: if the node under it is not a walkable block the node will be
|
* `attached_node`: the node is 'attached' to a neighboring node. It checks
|
||||||
dropped as an item. If the node is wallmounted the wallmounted direction is
|
whether the node it is attached to is walkable. If it
|
||||||
checked.
|
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.
|
* `bouncy`: value is bounce speed in percent.
|
||||||
If positive, jump/sneak on floor impact will increase/decrease bounce height.
|
If positive, jump/sneak on floor impact will increase/decrease bounce height.
|
||||||
Negative value is the same bounciness, but non-controllable.
|
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 },
|
groups = { attached_node = 1, dig_immediate = 3 },
|
||||||
})
|
})
|
||||||
|
|
||||||
-- This node attaches to the side of a node and drops as item
|
-- This node attaches to the side of a node and drops as item
|
||||||
-- when the node it attaches to is gone.
|
-- when the node it attaches to is gone.
|
||||||
minetest.register_node("testnodes:attached_wallmounted", {
|
minetest.register_node("testnodes:attached_wallmounted", {
|
||||||
@ -73,6 +72,61 @@ minetest.register_node("testnodes:attached_wallmounted", {
|
|||||||
groups = { attached_node = 1, dig_immediate = 3 },
|
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
|
-- Jump disabled
|
||||||
minetest.register_node("testnodes:nojump", {
|
minetest.register_node("testnodes:nojump", {
|
||||||
description = S("Non-jumping Node").."\n"..
|
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
|
// Check attachment if node is in group attached_node
|
||||||
if (itemgroup_get(predicted_f.groups, "attached_node") != 0) {
|
int an = itemgroup_get(predicted_f.groups, "attached_node");
|
||||||
const static v3s16 wallmounted_dirs[8] = {
|
if (an != 0) {
|
||||||
v3s16(0, 1, 0),
|
|
||||||
v3s16(0, -1, 0),
|
|
||||||
v3s16(1, 0, 0),
|
|
||||||
v3s16(-1, 0, 0),
|
|
||||||
v3s16(0, 0, 1),
|
|
||||||
v3s16(0, 0, -1),
|
|
||||||
};
|
|
||||||
v3s16 pp;
|
v3s16 pp;
|
||||||
|
|
||||||
if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
|
if (an == 3) {
|
||||||
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)
|
|
||||||
pp = p + wallmounted_dirs[param2];
|
|
||||||
else
|
|
||||||
pp = p + v3s16(0, -1, 0);
|
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) {
|
if (!nodedef->get(map.getNode(pp)).walkable) {
|
||||||
soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
|
soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
|
||||||
|
@ -118,3 +118,52 @@ const u8 wallmounted_to_facedir[6] = {
|
|||||||
8,
|
8,
|
||||||
4 + 2
|
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 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.
|
/// Direction in the 6D format. g_27dirs contains corresponding vectors.
|
||||||
/// Here P means Positive, N stands for Negative.
|
/// Here P means Positive, N stands for Negative.
|
||||||
enum Direction6D {
|
enum Direction6D {
|
||||||
|
Loading…
Reference in New Issue
Block a user