Skip to content

Commit

Permalink
Fix connected nodes' selection boxes.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sofar authored and paramat committed Mar 21, 2016
1 parent 493a298 commit 80cec47
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 6 deletions.
50 changes: 47 additions & 3 deletions src/game.cpp
Expand Up @@ -273,6 +273,49 @@ inline bool isPointableNode(const MapNode &n,
(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
*/
Expand Down Expand Up @@ -350,8 +393,9 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio
for (s16 x = xstart; x <= xend; x++) {
MapNode n;
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) {
continue;
}
Expand All @@ -360,7 +404,7 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio
}

std::vector<aabb3f> boxes;
n.getSelectionBoxes(nodedef, &boxes);
n.getSelectionBoxes(nodedef, &boxes, getNeighbors(p, nodedef, &map, n));

v3s16 np(x, y, z);
v3f npf = intToFloat(np, BS);
Expand Down Expand Up @@ -392,7 +436,7 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio
MapNode n = map.getNodeNoEx(pointed_pos);
v3f npf = intToFloat(pointed_pos, BS);
std::vector<aabb3f> boxes;
n.getSelectionBoxes(nodedef, &boxes);
n.getSelectionBoxes(nodedef, &boxes, getNeighbors(pointed_pos, nodedef, &map, n));
f32 face_min_distance = 1000 * BS;
for (std::vector<aabb3f>::const_iterator
i = boxes.begin();
Expand Down
4 changes: 2 additions & 2 deletions src/mapnode.cpp
Expand Up @@ -456,10 +456,10 @@ void MapNode::getCollisionBoxes(INodeDefManager *nodemgr, std::vector<aabb3f> *b
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);
transformNodeBox(*this, f.selection_box, nodemgr, boxes);
transformNodeBox(*this, f.selection_box, nodemgr, boxes, neighbors);
}

u8 MapNode::getMaxLevel(INodeDefManager *nodemgr) const
Expand Down
2 changes: 1 addition & 1 deletion src/mapnode.h
Expand Up @@ -245,7 +245,7 @@ struct MapNode
/*
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
Expand Down

0 comments on commit 80cec47

Please sign in to comment.