forked from Mirrorlandia_minetest/minetest
Fix connected nodes' selection boxes.
This allows the player to more easily target and punch connected nodeboxes, especially if they have a fixed nodebox that is very small, like technic cabling, or xpanes. Tried it on fences and my xpane conversion, and happy with the result.
This commit is contained in:
parent
493a298c0c
commit
80cec4702d
50
src/game.cpp
50
src/game.cpp
@ -273,6 +273,49 @@ inline bool isPointableNode(const MapNode &n,
|
|||||||
(liquids_pointable && features.isLiquid());
|
(liquids_pointable && features.isLiquid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void getNeighborConnectingFace(v3s16 p, INodeDefManager *nodedef,
|
||||||
|
ClientMap *map, MapNode n, u8 bitmask, u8 *neighbors)
|
||||||
|
{
|
||||||
|
MapNode n2 = map->getNodeNoEx(p);
|
||||||
|
if (nodedef->nodeboxConnects(n, n2, bitmask))
|
||||||
|
*neighbors |= bitmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u8 getNeighbors(v3s16 p, INodeDefManager *nodedef, ClientMap *map, MapNode n)
|
||||||
|
{
|
||||||
|
u8 neighbors = 0;
|
||||||
|
const ContentFeatures &f = nodedef->get(n);
|
||||||
|
// locate possible neighboring nodes to connect to
|
||||||
|
if (f.drawtype == NDT_NODEBOX && f.node_box.type == NODEBOX_CONNECTED) {
|
||||||
|
v3s16 p2 = p;
|
||||||
|
|
||||||
|
p2.Y++;
|
||||||
|
getNeighborConnectingFace(p2, nodedef, map, n, 1, &neighbors);
|
||||||
|
|
||||||
|
p2 = p;
|
||||||
|
p2.Y--;
|
||||||
|
getNeighborConnectingFace(p2, nodedef, map, n, 2, &neighbors);
|
||||||
|
|
||||||
|
p2 = p;
|
||||||
|
p2.Z--;
|
||||||
|
getNeighborConnectingFace(p2, nodedef, map, n, 4, &neighbors);
|
||||||
|
|
||||||
|
p2 = p;
|
||||||
|
p2.X--;
|
||||||
|
getNeighborConnectingFace(p2, nodedef, map, n, 8, &neighbors);
|
||||||
|
|
||||||
|
p2 = p;
|
||||||
|
p2.Z++;
|
||||||
|
getNeighborConnectingFace(p2, nodedef, map, n, 16, &neighbors);
|
||||||
|
|
||||||
|
p2 = p;
|
||||||
|
p2.X++;
|
||||||
|
getNeighborConnectingFace(p2, nodedef, map, n, 32, &neighbors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return neighbors;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Find what the player is pointing at
|
Find what the player is pointing at
|
||||||
*/
|
*/
|
||||||
@ -350,8 +393,9 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio
|
|||||||
for (s16 x = xstart; x <= xend; x++) {
|
for (s16 x = xstart; x <= xend; x++) {
|
||||||
MapNode n;
|
MapNode n;
|
||||||
bool is_valid_position;
|
bool is_valid_position;
|
||||||
|
v3s16 p(x, y, z);
|
||||||
|
|
||||||
n = map.getNodeNoEx(v3s16(x, y, z), &is_valid_position);
|
n = map.getNodeNoEx(p, &is_valid_position);
|
||||||
if (!is_valid_position) {
|
if (!is_valid_position) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -360,7 +404,7 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<aabb3f> boxes;
|
std::vector<aabb3f> boxes;
|
||||||
n.getSelectionBoxes(nodedef, &boxes);
|
n.getSelectionBoxes(nodedef, &boxes, getNeighbors(p, nodedef, &map, n));
|
||||||
|
|
||||||
v3s16 np(x, y, z);
|
v3s16 np(x, y, z);
|
||||||
v3f npf = intToFloat(np, BS);
|
v3f npf = intToFloat(np, BS);
|
||||||
@ -392,7 +436,7 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio
|
|||||||
MapNode n = map.getNodeNoEx(pointed_pos);
|
MapNode n = map.getNodeNoEx(pointed_pos);
|
||||||
v3f npf = intToFloat(pointed_pos, BS);
|
v3f npf = intToFloat(pointed_pos, BS);
|
||||||
std::vector<aabb3f> boxes;
|
std::vector<aabb3f> boxes;
|
||||||
n.getSelectionBoxes(nodedef, &boxes);
|
n.getSelectionBoxes(nodedef, &boxes, getNeighbors(pointed_pos, nodedef, &map, n));
|
||||||
f32 face_min_distance = 1000 * BS;
|
f32 face_min_distance = 1000 * BS;
|
||||||
for (std::vector<aabb3f>::const_iterator
|
for (std::vector<aabb3f>::const_iterator
|
||||||
i = boxes.begin();
|
i = boxes.begin();
|
||||||
|
@ -456,10 +456,10 @@ void MapNode::getCollisionBoxes(INodeDefManager *nodemgr, std::vector<aabb3f> *b
|
|||||||
transformNodeBox(*this, f.collision_box, nodemgr, boxes, neighbors);
|
transformNodeBox(*this, f.collision_box, nodemgr, boxes, neighbors);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapNode::getSelectionBoxes(INodeDefManager *nodemgr, std::vector<aabb3f> *boxes)
|
void MapNode::getSelectionBoxes(INodeDefManager *nodemgr, std::vector<aabb3f> *boxes, u8 neighbors)
|
||||||
{
|
{
|
||||||
const ContentFeatures &f = nodemgr->get(*this);
|
const ContentFeatures &f = nodemgr->get(*this);
|
||||||
transformNodeBox(*this, f.selection_box, nodemgr, boxes);
|
transformNodeBox(*this, f.selection_box, nodemgr, boxes, neighbors);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 MapNode::getMaxLevel(INodeDefManager *nodemgr) const
|
u8 MapNode::getMaxLevel(INodeDefManager *nodemgr) const
|
||||||
|
@ -245,7 +245,7 @@ struct MapNode
|
|||||||
/*
|
/*
|
||||||
Gets list of selection boxes
|
Gets list of selection boxes
|
||||||
*/
|
*/
|
||||||
void getSelectionBoxes(INodeDefManager *nodemg, std::vector<aabb3f> *boxes);
|
void getSelectionBoxes(INodeDefManager *nodemg, std::vector<aabb3f> *boxes, u8 neighbors = 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Gets list of collision boxes
|
Gets list of collision boxes
|
||||||
|
Loading…
Reference in New Issue
Block a user