Fix connected nodes' selection boxes.
authorAuke Kok <sofar@foo-projects.org>
Tue, 15 Mar 2016 06:20:56 +0000 (23:20 -0700)
committerparamat <mat.gregory@virginmedia.com>
Mon, 21 Mar 2016 17:42:20 +0000 (17:42 +0000)
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
src/mapnode.cpp
src/mapnode.h

index be4c46bc353970e2cbcfaaefe9ab59d6bd7d0cfb..c1f80c5a1cfc6e6698c690fdb86ed1785330643c 100644 (file)
@@ -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<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);
@@ -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();
index a5465887339b4daec44dff574a8386d0de6004ab..eba47446d99ac1e0b56a0a2ae03ed159ef98ff64 100644 (file)
@@ -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
index 4db8886160b619b5c7d8b4de2f4e757777c90d6a..2f6224f0279073791f23d0369679a33b54be2fbb 100644 (file)
@@ -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