aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to '')
-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
4 files changed, 63 insertions, 9 deletions
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);
}