aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/lua_api.txt8
-rw-r--r--src/activeobject.h4
-rw-r--r--src/client/content_cao.cpp56
-rw-r--r--src/client/content_cao.h8
-rw-r--r--src/client/game.cpp3
-rw-r--r--src/clientiface.cpp5
-rw-r--r--src/script/lua_api/l_camera.cpp3
-rw-r--r--src/script/lua_api/l_object.cpp14
-rw-r--r--src/server/luaentity_sao.cpp4
-rw-r--r--src/server/player_sao.cpp9
-rw-r--r--src/server/unit_sao.cpp17
-rw-r--r--src/server/unit_sao.h5
12 files changed, 101 insertions, 35 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index c21da1871..77fb4a654 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -6167,12 +6167,14 @@ object you are working with still exists.
`frame_loop`.
* `set_animation_frame_speed(frame_speed)`
* `frame_speed`: number, default: `15.0`
-* `set_attach(parent, bone, position, rotation)`
+* `set_attach(parent, bone, position, rotation, forced_visible)`
* `bone`: string
* `position`: `{x=num, y=num, z=num}` (relative)
* `rotation`: `{x=num, y=num, z=num}` = Rotation on each axis, in degrees
-* `get_attach()`: returns parent, bone, position, rotation or nil if it isn't
- attached.
+ * `forced_visible`: Boolean to control whether the attached entity
+ should appear in first person.
+* `get_attach()`: returns parent, bone, position, rotation, forced_visible,
+ or nil if it isn't attached.
* `set_detach()`
* `set_bone_position(bone, position, rotation)`
* `bone`: string
diff --git a/src/activeobject.h b/src/activeobject.h
index 85e160d10..0829858ad 100644
--- a/src/activeobject.h
+++ b/src/activeobject.h
@@ -120,9 +120,9 @@ public:
virtual void setAttachment(int parent_id, const std::string &bone, v3f position,
- v3f rotation) {}
+ v3f rotation, bool force_visible) {}
virtual void getAttachment(int *parent_id, std::string *bone, v3f *position,
- v3f *rotation) const {}
+ v3f *rotation, bool *force_visible) const {}
virtual void clearChildAttachments() {}
virtual void clearParentAttachment() {}
virtual void addAttachmentChild(int child_id) {}
diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp
index c1715a289..fae06554a 100644
--- a/src/client/content_cao.cpp
+++ b/src/client/content_cao.cpp
@@ -456,7 +456,8 @@ void GenericCAO::setChildrenVisible(bool toset)
for (u16 cao_id : m_attachment_child_ids) {
GenericCAO *obj = m_env->getGenericCAO(cao_id);
if (obj) {
- obj->setVisible(toset);
+ // Check if the entity is forced to appear in first person.
+ obj->setVisible(obj->isForcedVisible() ? true : toset);
}
}
}
@@ -477,8 +478,6 @@ void GenericCAO::setAttachment(int parent_id, const std::string &bone, v3f posit
if (parent)
parent->addAttachmentChild(m_id);
}
-
-
updateAttachments();
}
@@ -498,7 +497,7 @@ void GenericCAO::clearChildAttachments()
int child_id = *m_attachment_child_ids.begin();
if (ClientActiveObject *child = m_env->getActiveObject(child_id))
- child->setAttachment(0, "", v3f(), v3f());
+ child->setAttachment(0, "", v3f(), v3f(), false);
removeAttachmentChild(child_id);
}
@@ -800,6 +799,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc)
updateBonePosition();
updateAttachments();
setNodeLight(m_last_light);
+ updateMeshCulling();
}
void GenericCAO::updateLight(u32 day_night_ratio)
@@ -1411,6 +1411,9 @@ void GenericCAO::updateTextures(std::string mod)
setMeshColor(mesh, m_prop.colors[0]);
}
}
+ // Prevent showing the player after changing texture
+ if (m_is_local_player)
+ updateMeshCulling();
}
void GenericCAO::updateAnimation()
@@ -1739,12 +1742,25 @@ void GenericCAO::processMessage(const std::string &data)
std::string bone = deSerializeString16(is);
v3f position = readV3F32(is);
v3f rotation = readV3F32(is);
+ m_force_visible = readU8(is); // Returns false for EOF
setAttachment(parent_id, bone, position, rotation);
+ // Forcibly show attachments if required by set_attach
+ if (m_force_visible)
+ m_is_visible = true;
// localplayer itself can't be attached to localplayer
- if (!m_is_local_player)
- m_is_visible = !m_attached_to_local;
+ else if (!m_is_local_player) {
+ // Objects attached to the local player should be hidden in first
+ // person provided the forced boolean isn't set.
+ m_is_visible = !m_attached_to_local ||
+ m_client->getCamera()->getCameraMode() != CAMERA_MODE_FIRST;
+ m_force_visible = false;
+ } else {
+ // Local players need to have this set,
+ // otherwise first person attachments fail.
+ m_is_visible = true;
+ }
} else if (cmd == AO_CMD_PUNCHED) {
u16 result_hp = readU16(is);
@@ -1858,5 +1874,33 @@ std::string GenericCAO::debugInfoText()
return os.str();
}
+void GenericCAO::updateMeshCulling()
+{
+ if (!m_is_local_player)
+ return;
+
+ // Grab the active player scene node so we know there's
+ // at least a mesh to occlude from the camera.
+ irr::scene::ISceneNode *node = getSceneNode();
+ if (!node)
+ return;
+
+ if (m_client->getCamera()->getCameraMode() == CAMERA_MODE_FIRST) {
+ // Hide the mesh by culling both front and
+ // back faces. Serious hackyness but it works for our
+ // purposes. This also preserves the skeletal armature.
+ node->setMaterialFlag(video::EMF_BACK_FACE_CULLING,
+ true);
+ node->setMaterialFlag(video::EMF_FRONT_FACE_CULLING,
+ true);
+ } else {
+ // Restore mesh visibility.
+ node->setMaterialFlag(video::EMF_BACK_FACE_CULLING,
+ m_prop.backface_culling);
+ node->setMaterialFlag(video::EMF_FRONT_FACE_CULLING,
+ false);
+ }
+}
+
// Prototype
GenericCAO proto_GenericCAO(NULL, NULL);
diff --git a/src/client/content_cao.h b/src/client/content_cao.h
index 974ff9a1e..daf697767 100644
--- a/src/client/content_cao.h
+++ b/src/client/content_cao.h
@@ -124,6 +124,7 @@ private:
float m_step_distance_counter = 0.0f;
u8 m_last_light = 255;
bool m_is_visible = false;
+ bool m_force_visible = false;
s8 m_glow = 0;
// Material
video::E_MATERIAL_TYPE m_material_type;
@@ -215,6 +216,11 @@ public:
m_is_visible = toset;
}
+ inline bool isForcedVisible() const
+ {
+ return m_force_visible;
+ }
+
void setChildrenVisible(bool toset);
void setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation);
void getAttachment(int *parent_id, std::string *bone, v3f *position,
@@ -275,4 +281,6 @@ public:
{
return m_prop.infotext;
}
+
+ void updateMeshCulling();
};
diff --git a/src/client/game.cpp b/src/client/game.cpp
index 8f9d51417..366464467 100644
--- a/src/client/game.cpp
+++ b/src/client/game.cpp
@@ -2950,7 +2950,8 @@ void Game::updateCamera(u32 busy_time, f32 dtime)
camera->toggleCameraMode();
- playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
+ // Make the player visible depending on camera mode.
+ playercao->updateMeshCulling();
playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
}
diff --git a/src/clientiface.cpp b/src/clientiface.cpp
index 602a44c90..28a0ee770 100644
--- a/src/clientiface.cpp
+++ b/src/clientiface.cpp
@@ -80,10 +80,11 @@ LuaEntitySAO *getAttachedObject(PlayerSAO *sao, ServerEnvironment *env)
int id;
std::string bone;
v3f dummy;
- sao->getAttachment(&id, &bone, &dummy, &dummy);
+ bool force_visible;
+ sao->getAttachment(&id, &bone, &dummy, &dummy, &force_visible);
ServerActiveObject *ao = env->getActiveObject(id);
while (id && ao) {
- ao->getAttachment(&id, &bone, &dummy, &dummy);
+ ao->getAttachment(&id, &bone, &dummy, &dummy, &force_visible);
if (id)
ao = env->getActiveObject(id);
}
diff --git a/src/script/lua_api/l_camera.cpp b/src/script/lua_api/l_camera.cpp
index bfa60be67..40251154c 100644
--- a/src/script/lua_api/l_camera.cpp
+++ b/src/script/lua_api/l_camera.cpp
@@ -63,7 +63,8 @@ int LuaCamera::l_set_camera_mode(lua_State *L)
return 0;
camera->setCameraMode((CameraMode)((int)lua_tonumber(L, 2)));
- playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
+ // Make the player visible depending on camera mode.
+ playercao->updateMeshCulling();
playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
return 0;
}
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index 303b1175b..fead4e849 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -664,7 +664,7 @@ int ObjectRef::l_get_bone_position(lua_State *L)
return 2;
}
-// set_attach(self, parent, bone, position, rotation)
+// set_attach(self, parent, bone, position, rotation, force_visible)
int ObjectRef::l_set_attach(lua_State *L)
{
GET_ENV_PTR;
@@ -687,7 +687,8 @@ int ObjectRef::l_set_attach(lua_State *L)
std::string bone;
v3f position = v3f(0, 0, 0);
v3f rotation = v3f(0, 0, 0);
- co->getAttachment(&parent_id, &bone, &position, &rotation);
+ bool force_visible;
+ co->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible);
if (parent_id) {
ServerActiveObject *old_parent = env->getActiveObject(parent_id);
old_parent->removeAttachmentChild(co->getId());
@@ -702,7 +703,8 @@ int ObjectRef::l_set_attach(lua_State *L)
rotation = v3f(0, 0, 0);
if (!lua_isnil(L, 5))
rotation = read_v3f(L, 5);
- co->setAttachment(parent->getId(), bone, position, rotation);
+ force_visible = readParam<bool>(L, 6, false);
+ co->setAttachment(parent->getId(), bone, position, rotation, force_visible);
parent->addAttachmentChild(co->getId());
return 0;
}
@@ -722,7 +724,8 @@ int ObjectRef::l_get_attach(lua_State *L)
std::string bone;
v3f position = v3f(0, 0, 0);
v3f rotation = v3f(0, 0, 0);
- co->getAttachment(&parent_id, &bone, &position, &rotation);
+ bool force_visible;
+ co->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible);
if (!parent_id)
return 0;
ServerActiveObject *parent = env->getActiveObject(parent_id);
@@ -731,7 +734,8 @@ int ObjectRef::l_get_attach(lua_State *L)
lua_pushlstring(L, bone.c_str(), bone.size());
push_v3f(L, position);
push_v3f(L, rotation);
- return 4;
+ lua_pushboolean(L, force_visible);
+ return 5;
}
// set_detach(self)
diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp
index f20914f7f..b39797531 100644
--- a/src/server/luaentity_sao.cpp
+++ b/src/server/luaentity_sao.cpp
@@ -238,9 +238,9 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version)
msg_os << serializeString32(generateUpdateAnimationCommand()); // 3
for (const auto &bone_pos : m_bone_position) {
msg_os << serializeString32(generateUpdateBonePositionCommand(
- bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // m_bone_position.size
+ bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // 3 + N
}
- msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4
+ msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + m_bone_position.size
int message_count = 4 + m_bone_position.size();
diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp
index 8d4938c3c..344d18a20 100644
--- a/src/server/player_sao.cpp
+++ b/src/server/player_sao.cpp
@@ -122,10 +122,10 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
msg_os << serializeString32(generateUpdateAnimationCommand()); // 3
for (const auto &bone_pos : m_bone_position) {
msg_os << serializeString32(generateUpdateBonePositionCommand(
- bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // m_bone_position.size
+ bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // 3 + N
}
- msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4
- msg_os << serializeString32(generateUpdatePhysicsOverrideCommand()); // 5
+ msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + m_bone_position.size
+ msg_os << serializeString32(generateUpdatePhysicsOverrideCommand()); // 5 + m_bone_position.size
int message_count = 5 + m_bone_position.size();
@@ -569,7 +569,8 @@ bool PlayerSAO::checkMovementCheat()
int parent_id;
std::string bone;
v3f attachment_rot;
- getAttachment(&parent_id, &bone, &attachment_pos, &attachment_rot);
+ bool force_visible;
+ getAttachment(&parent_id, &bone, &attachment_pos, &attachment_rot, &force_visible);
}
v3f parent_pos = parent->getBasePosition();
diff --git a/src/server/unit_sao.cpp b/src/server/unit_sao.cpp
index d906e885e..2371640ca 100644
--- a/src/server/unit_sao.cpp
+++ b/src/server/unit_sao.cpp
@@ -121,8 +121,8 @@ void UnitSAO::sendOutdatedData()
}
// clang-format on
-void UnitSAO::setAttachment(
- int parent_id, const std::string &bone, v3f position, v3f rotation)
+void UnitSAO::setAttachment(int parent_id, const std::string &bone, v3f position,
+ v3f rotation, bool force_visible)
{
// Attachments need to be handled on both the server and client.
// If we just attach on the server, we can only copy the position of the parent.
@@ -137,6 +137,7 @@ void UnitSAO::setAttachment(
m_attachment_bone = bone;
m_attachment_position = position;
m_attachment_rotation = rotation;
+ m_force_visible = force_visible;
m_attachment_sent = false;
if (parent_id != old_parent) {
@@ -145,13 +146,14 @@ void UnitSAO::setAttachment(
}
}
-void UnitSAO::getAttachment(
- int *parent_id, std::string *bone, v3f *position, v3f *rotation) const
+void UnitSAO::getAttachment(int *parent_id, std::string *bone, v3f *position,
+ v3f *rotation, bool *force_visible) const
{
*parent_id = m_attachment_parent_id;
*bone = m_attachment_bone;
*position = m_attachment_position;
*rotation = m_attachment_rotation;
+ *force_visible = m_force_visible;
}
void UnitSAO::clearChildAttachments()
@@ -159,7 +161,7 @@ void UnitSAO::clearChildAttachments()
for (int child_id : m_attachment_child_ids) {
// Child can be NULL if it was deleted earlier
if (ServerActiveObject *child = m_env->getActiveObject(child_id))
- child->setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0));
+ child->setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0), false);
}
m_attachment_child_ids.clear();
}
@@ -169,9 +171,9 @@ void UnitSAO::clearParentAttachment()
ServerActiveObject *parent = nullptr;
if (m_attachment_parent_id) {
parent = m_env->getActiveObject(m_attachment_parent_id);
- setAttachment(0, "", m_attachment_position, m_attachment_rotation);
+ setAttachment(0, "", m_attachment_position, m_attachment_rotation, false);
} else {
- setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0));
+ setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0), false);
}
// Do it
if (parent)
@@ -245,6 +247,7 @@ std::string UnitSAO::generateUpdateAttachmentCommand() const
os << serializeString16(m_attachment_bone);
writeV3F32(os, m_attachment_position);
writeV3F32(os, m_attachment_rotation);
+ writeU8(os, m_force_visible);
return os.str();
}
diff --git a/src/server/unit_sao.h b/src/server/unit_sao.h
index 3cb7f0ad5..a21e055c5 100644
--- a/src/server/unit_sao.h
+++ b/src/server/unit_sao.h
@@ -64,9 +64,9 @@ public:
ServerActiveObject *getParent() const;
inline bool isAttached() const { return getParent(); }
void setAttachment(int parent_id, const std::string &bone, v3f position,
- v3f rotation);
+ v3f rotation, bool force_visible);
void getAttachment(int *parent_id, std::string *bone, v3f *position,
- v3f *rotation) const;
+ v3f *rotation, bool *force_visible) const;
void clearChildAttachments();
void clearParentAttachment();
void addAttachmentChild(int child_id);
@@ -133,4 +133,5 @@ private:
v3f m_attachment_position;
v3f m_attachment_rotation;
bool m_attachment_sent = false;
+ bool m_force_visible = false;
};