From 80cec4702dde598ded6a5b31e291d2973b26cc7b Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Mon, 14 Mar 2016 23:20:56 -0700 Subject: [PATCH] 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. --- src/game.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++--- src/mapnode.cpp | 4 ++-- src/mapnode.h | 2 +- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index be4c46bc3..c1f80c5a1 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -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 */ @@ -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; } @@ -360,7 +404,7 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio } std::vector boxes; - n.getSelectionBoxes(nodedef, &boxes); + n.getSelectionBoxes(nodedef, &boxes, getNeighbors(p, nodedef, &map, n)); v3s16 np(x, y, z); 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); v3f npf = intToFloat(pointed_pos, BS); std::vector boxes; - n.getSelectionBoxes(nodedef, &boxes); + n.getSelectionBoxes(nodedef, &boxes, getNeighbors(pointed_pos, nodedef, &map, n)); f32 face_min_distance = 1000 * BS; for (std::vector::const_iterator i = boxes.begin(); diff --git a/src/mapnode.cpp b/src/mapnode.cpp index a54658873..eba47446d 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -456,10 +456,10 @@ void MapNode::getCollisionBoxes(INodeDefManager *nodemgr, std::vector *b transformNodeBox(*this, f.collision_box, nodemgr, boxes, neighbors); } -void MapNode::getSelectionBoxes(INodeDefManager *nodemgr, std::vector *boxes) +void MapNode::getSelectionBoxes(INodeDefManager *nodemgr, std::vector *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 diff --git a/src/mapnode.h b/src/mapnode.h index 4db888616..2f6224f02 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -245,7 +245,7 @@ struct MapNode /* Gets list of selection boxes */ - void getSelectionBoxes(INodeDefManager *nodemg, std::vector *boxes); + void getSelectionBoxes(INodeDefManager *nodemg, std::vector *boxes, u8 neighbors = 0); /* Gets list of collision boxes