aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAuke Kok <sofar@foo-projects.org>2016-03-03 23:18:04 -0800
committerShadowNinja <shadowninja@minetest.net>2016-03-12 12:08:17 -0500
commit37b4f0d34c73de58e0f5d153b7e699dc7430e23d (patch)
tree5c1f23df722ef9bc2c1110d78016439b26b35772
parente737b1c271c9d957651ef2201bb820e4465358bf (diff)
downloadminetest-37b4f0d34c73de58e0f5d153b7e699dc7430e23d.tar.gz
minetest-37b4f0d34c73de58e0f5d153b7e699dc7430e23d.tar.bz2
minetest-37b4f0d34c73de58e0f5d153b7e699dc7430e23d.zip
Allow nodes to specify which sides to connect to.
NDT_CONNECTED attempts to connect to any side of nodes that it can connect to, which is troublesome for FACEDIR type nodes that generally may only have one usable face, and can be rotated. We introduce a node parameter `connect_sides` that is valid for any node type. If specified, it lists faces of the node (in "top", "bottom", "front", "left", "back", "right", form, as array) that connecting nodeboxes can connect to. "front" corresponds to the south facing side of a node with facedir = 0. If the node is rotatable using *simple* FACEDIR, then the attached face is properly rotated before checking. This allows e.g. a chest to be attached to only from the rear side.
-rw-r--r--doc/lua_api.txt2
-rw-r--r--src/collision.cpp2
-rw-r--r--src/content_mapblock.cpp2
-rw-r--r--src/nodedef.cpp25
-rw-r--r--src/nodedef.h4
-rw-r--r--src/script/common/c_content.cpp28
6 files changed, 58 insertions, 5 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index f51c950c3..733ac8412 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -3477,6 +3477,8 @@ Definition tables
* Used for nodebox nodes with the type == "connected"
* Specifies to what neighboring nodes connections will be drawn
* e.g. `{"group:fence", "default:wood"}` or `"default:stone"` ]]
+ connect_sides = { "top", "bottom", "front", "left", "back", "right" }, --[[
+ ^ Tells connected nodebox nodes to connect only to these sides of this node. ]]
mesh = "model",
selection_box = {type="regular"}, -- See "Node boxes" --[[
^ If drawtype "nodebox" is used and selection_box is nil, then node_box is used. ]]
diff --git a/src/collision.cpp b/src/collision.cpp
index a3979f1dc..16db3310c 100644
--- a/src/collision.cpp
+++ b/src/collision.cpp
@@ -189,7 +189,7 @@ static inline void getNeighborConnectingFace(v3s16 p, INodeDefManager *nodedef,
Map *map, MapNode n, int v, int *neighbors)
{
MapNode n2 = map->getNodeNoEx(p);
- if (nodedef->nodeboxConnects(n, n2))
+ if (nodedef->nodeboxConnects(n, n2, v))
*neighbors |= v;
}
diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp
index c2934f26a..6a83bd8f3 100644
--- a/src/content_mapblock.cpp
+++ b/src/content_mapblock.cpp
@@ -167,7 +167,7 @@ static inline void getNeighborConnectingFace(v3s16 p, INodeDefManager *nodedef,
MeshMakeData *data, MapNode n, int v, int *neighbors)
{
MapNode n2 = data->m_vmanip.getNodeNoEx(p);
- if (nodedef->nodeboxConnects(n, n2))
+ if (nodedef->nodeboxConnects(n, n2, v))
*neighbors |= v;
}
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index 85cd848ae..edd02d9f3 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -331,6 +331,7 @@ void ContentFeatures::reset()
sound_dug = SimpleSoundSpec();
connects_to.clear();
connects_to_ids.clear();
+ connect_sides = 0;
}
void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
@@ -402,6 +403,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
for (std::set<content_t>::const_iterator i = connects_to_ids.begin();
i != connects_to_ids.end(); ++i)
writeU16(os, *i);
+ writeU8(os, connect_sides);
}
void ContentFeatures::deSerialize(std::istream &is)
@@ -479,6 +481,7 @@ void ContentFeatures::deSerialize(std::istream &is)
u16 connects_to_size = readU16(is);
for (u16 i = 0; i < connects_to_size; i++)
connects_to_ids.insert(readU16(is));
+ connect_sides = readU8(is);
}catch(SerializationError &e) {};
}
@@ -517,7 +520,7 @@ public:
virtual void runNodeResolveCallbacks();
virtual void resetNodeResolveState();
virtual void mapNodeboxConnections();
- virtual bool nodeboxConnects(MapNode from, MapNode to);
+ virtual bool nodeboxConnects(MapNode from, MapNode to, u8 connect_face);
private:
void addNameIdMapping(content_t i, std::string name);
@@ -1530,7 +1533,7 @@ void CNodeDefManager::mapNodeboxConnections()
}
}
-bool CNodeDefManager::nodeboxConnects(MapNode from, MapNode to)
+bool CNodeDefManager::nodeboxConnects(MapNode from, MapNode to, u8 connect_face)
{
const ContentFeatures &f1 = get(from);
@@ -1547,6 +1550,24 @@ bool CNodeDefManager::nodeboxConnects(MapNode from, MapNode to)
// ignores actually looking if back connection exists
return (f2.connects_to_ids.find(from.param0) != f2.connects_to_ids.end());
+ // does to node declare usable faces?
+ if (f2.connect_sides > 0) {
+ if ((f2.param_type_2 == CPT2_FACEDIR) && (connect_face >= 4)) {
+ static const u8 rot[33 * 4] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 32, 16, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 - back
+ 8, 4, 32, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 - right
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 16, 8, 4, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - front
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 32, 16, 8, 4 // 32 - left
+ };
+ return (f2.connect_sides & rot[(connect_face * 4) + to.param2]);
+ }
+ return (f2.connect_sides & connect_face);
+ }
// the target is just a regular node, so connect no matter back connection
return true;
}
diff --git a/src/nodedef.h b/src/nodedef.h
index f92a3a941..58d0faffa 100644
--- a/src/nodedef.h
+++ b/src/nodedef.h
@@ -271,6 +271,8 @@ struct ContentFeatures
bool legacy_facedir_simple;
// Set to true if wall_mounted used to be set to true
bool legacy_wallmounted;
+ // for NDT_CONNECTED pairing
+ u8 connect_sides;
// Sound properties
SimpleSoundSpec sound_footstep;
@@ -325,7 +327,7 @@ public:
virtual void pendNodeResolve(NodeResolver *nr)=0;
virtual bool cancelNodeResolveCallback(NodeResolver *nr)=0;
- virtual bool nodeboxConnects(const MapNode from, const MapNode to)=0;
+ virtual bool nodeboxConnects(const MapNode from, const MapNode to, u8 connect_face)=0;
};
class IWritableNodeDefManager : public INodeDefManager {
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index ababf0718..06e20c2a0 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -547,6 +547,34 @@ ContentFeatures read_content_features(lua_State *L, int index)
}
lua_pop(L, 1);
+ lua_getfield(L, index, "connect_sides");
+ if (lua_istable(L, -1)) {
+ int table = lua_gettop(L);
+ lua_pushnil(L);
+ while (lua_next(L, table) != 0) {
+ // Value at -1
+ std::string side(lua_tostring(L, -1));
+ // Note faces are flipped to make checking easier
+ if (side == "top")
+ f.connect_sides |= 2;
+ else if (side == "bottom")
+ f.connect_sides |= 1;
+ else if (side == "front")
+ f.connect_sides |= 16;
+ else if (side == "left")
+ f.connect_sides |= 32;
+ else if (side == "back")
+ f.connect_sides |= 4;
+ else if (side == "right")
+ f.connect_sides |= 8;
+ else
+ warningstream << "Unknown value for \"connect_sides\": "
+ << side << std::endl;
+ lua_pop(L, 1);
+ }
+ }
+ lua_pop(L, 1);
+
lua_getfield(L, index, "selection_box");
if(lua_istable(L, -1))
f.selection_box = read_nodebox(L, -1);