Expand Up
@@ -17,36 +17,35 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include " content_cao.h"
#include < IBillboardSceneNode.h>
#include < ICameraSceneNode.h>
#include < ITextSceneNode.h>
#include < IBillboardSceneNode.h>
#include < IMeshManipulator.h>
#include < IAnimatedMeshSceneNode.h>
#include " content_cao.h"
#include " util/numeric.h" // For IntervalLimiter & setPitchYawRoll
#include " util/serialize.h"
#include " util/basic_macros.h"
#include " client/client.h"
#include " client/renderingengine.h"
#include " client/sound.h"
#include " client/tile.h"
#include " environment.h"
#include " util/basic_macros.h"
#include " util/numeric.h" // For IntervalLimiter & setPitchYawRoll
#include " util/serialize.h"
#include " camera.h" // CameraModes
#include " collision.h"
#include " settings.h"
#include " serialization.h" // For decompressZlib
#include " clientobject.h"
#include " mesh.h"
#include " itemdef.h"
#include " tool.h"
#include " content_cso.h"
#include " sound .h"
#include " nodedef .h"
#include " environment .h"
#include " itemdef .h"
#include " localplayer.h"
#include " map.h"
#include " camera.h" // CameraModes
#include " client.h"
#include " mesh.h"
#include " nodedef.h"
#include " serialization.h" // For decompressZlib
#include " settings.h"
#include " sound.h"
#include " tool.h"
#include " wieldmesh.h"
#include < algorithm>
#include < cmath>
#include " client/renderingengine.h"
class Settings ;
struct ToolCapabilities ;
Expand Down
Expand Up
@@ -305,6 +304,7 @@ void TestCAO::processMessage(const std::string &data)
*/
#include " genericobject.h"
#include " clientobject.h"
GenericCAO::GenericCAO (Client *client, ClientEnvironment *env):
ClientActiveObject(0 , client, env)
Expand Down
Expand Up
@@ -372,6 +372,7 @@ void GenericCAO::processInitData(const std::string &data)
m_position = readV3F32 (is);
m_rotation = readV3F32 (is);
m_hp = readU16 (is);
const u8 num_messages = readU8 (is);
for (int i = 0 ; i < num_messages; i++) {
Expand Down
Expand Up
@@ -443,51 +444,87 @@ scene::IAnimatedMeshSceneNode* GenericCAO::getAnimatedMeshSceneNode()
void GenericCAO::setChildrenVisible (bool toset)
{
for (u16 cao_id : m_children ) {
for (u16 cao_id : m_attachment_child_ids ) {
GenericCAO *obj = m_env->getGenericCAO (cao_id);
if (obj) {
obj->setVisible (toset);
}
}
}
void GenericCAO::setAttachments ( )
void GenericCAO::setAttachment ( int parent_id, const std::string &bone, v3f position, v3f rotation )
{
int old_parent = m_attachment_parent_id;
m_attachment_parent_id = parent_id;
m_attachment_bone = bone;
m_attachment_position = position;
m_attachment_rotation = rotation;
ClientActiveObject *parent = m_env->getActiveObject (parent_id);
if (parent_id != old_parent) {
if (auto *o = m_env->getActiveObject (old_parent))
o->removeAttachmentChild (m_id);
if (parent)
parent->addAttachmentChild (m_id);
}
updateAttachments ();
}
ClientActiveObject* GenericCAO::getParent () const
void GenericCAO::getAttachment (int *parent_id, std::string *bone, v3f *position,
v3f *rotation) const
{
*parent_id = m_attachment_parent_id;
*bone = m_attachment_bone;
*position = m_attachment_position;
*rotation = m_attachment_rotation;
}
void GenericCAO::clearChildAttachments ()
{
ClientActiveObject *obj = NULL ;
// Cannot use for-loop here: setAttachment() modifies 'm_attachment_child_ids'!
while (!m_attachment_child_ids.empty ()) {
int child_id = *m_attachment_child_ids.begin ();
u16 attached_id = m_env->attachement_parent_ids [getId ()];
if (ClientActiveObject *child = m_env->getActiveObject (child_id))
child->setAttachment (0 , " " , v3f (), v3f ());
if ((attached_id != 0 ) &&
(attached_id != getId ())) {
obj = m_env->getActiveObject (attached_id);
removeAttachmentChild (child_id);
}
return obj;
}
void GenericCAO::removeFromScene ( bool permanent )
void GenericCAO::clearParentAttachment ( )
{
// Should be true when removing the object permanently and false when refreshing (eg: updating visuals)
if ((m_env != NULL ) && (permanent))
{
for (u16 ci : m_children) {
if (m_env->attachement_parent_ids [ci] == getId ()) {
m_env->attachement_parent_ids [ci] = 0 ;
}
}
m_children.clear ();
if (m_attachment_parent_id)
setAttachment (0 , " " , m_attachment_position, m_attachment_rotation);
else
setAttachment (0 , " " , v3f (), v3f ());
}
m_env->attachement_parent_ids [getId ()] = 0 ;
void GenericCAO::addAttachmentChild (int child_id)
{
m_attachment_child_ids.insert (child_id);
}
LocalPlayer* player = m_env->getLocalPlayer ();
if (this == player->parent ) {
player->parent = nullptr ;
player->isAttached = false ;
}
void GenericCAO::removeAttachmentChild (int child_id)
{
m_attachment_child_ids.erase (child_id);
}
ClientActiveObject* GenericCAO::getParent () const
{
return m_attachment_parent_id ? m_env->getActiveObject (m_attachment_parent_id) :
nullptr ;
}
void GenericCAO::removeFromScene (bool permanent)
{
// Should be true when removing the object permanently
// and false when refreshing (eg: updating visuals)
if (m_env && permanent) {
clearChildAttachments ();
clearParentAttachment ();
}
if (m_meshnode) {
Expand Down
Expand Up
@@ -711,6 +748,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc)
updateTextures (m_current_texture_modifier);
scene::ISceneNode *node = getSceneNode ();
if (node && !m_prop.nametag .empty () && !m_is_local_player) {
// Add nametag
v3f pos;
Expand All
@@ -736,7 +774,7 @@ void GenericCAO::updateLight(u8 light_at_pos)
updateLightNoCheck (light_at_pos);
// Update light of all children
for (u16 i : m_children ) {
for (u16 i : m_attachment_child_ids ) {
ClientActiveObject *obj = m_env->getActiveObject (i);
if (obj) {
obj->updateLightNoCheck (light_at_pos);
Expand Down
Expand Up
@@ -871,31 +909,25 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
// Attachments, part 1: All attached objects must be unparented first,
// or Irrlicht causes a segmentation fault
for (auto ci = m_children.begin (); ci != m_children.end ();) {
if (m_env->attachement_parent_ids [*ci] != getId ()) {
ci = m_children.erase (ci);
continue ;
}
ClientActiveObject *obj = m_env->getActiveObject (*ci);
for (u16 cao_id : m_attachment_child_ids) {
ClientActiveObject *obj = m_env->getActiveObject (cao_id);
if (obj) {
scene::ISceneNode *child_node = obj->getSceneNode ();
// The node's parent is always an IDummyTraformationSceneNode,
// so we need to reparent that one instead.
if (child_node)
child_node->getParent ()->setParent (m_smgr->getRootSceneNode ());
}
++ci;
}
removeFromScene (false );
addToScene (m_client->tsrc ());
// Attachments, part 2: Now that the parent has been refreshed, put its attachments back
for (u16 cao_id : m_children) {
// Get the object of the child
for (u16 cao_id : m_attachment_child_ids) {
ClientActiveObject *obj = m_env->getActiveObject (cao_id);
if (obj)
obj->setAttachments ();
obj->updateAttachments ();
}
}
Expand All
@@ -916,7 +948,6 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
{
LocalPlayer *player = m_env->getLocalPlayer ();
player->overridePosition = getParent ()->getPosition ();
m_env->getLocalPlayer ()->parent = getParent ();
}
} else {
rot_translator.translate (dtime);
Expand Down
Expand Up
@@ -1296,17 +1327,21 @@ void GenericCAO::updateBonePosition()
void GenericCAO::updateAttachments ()
{
ClientActiveObject *parent = getParent ();
m_attached_to_local = parent && parent->isLocalPlayer ();
if (!parent && m_attachment_parent_id) {
// m_is_visible = false; maybe later. needs better handling
return ;
}
if (!parent) { // Detach or don't attach
if (m_matrixnode) {
v3f old_pos = m_matrixnode->getAbsolutePosition ();
m_matrixnode->setParent (m_smgr->getRootSceneNode ());
getPosRotMatrix ().setTranslation (old_pos);
m_matrixnode->updateAbsolutePosition ();
}
if (m_is_local_player) {
LocalPlayer *player = m_env->getLocalPlayer ();
player->isAttached = false ;
}
}
else // Attach
{
Expand All
@@ -1325,10 +1360,11 @@ void GenericCAO::updateAttachments()
getPosRotMatrix ().setRotationDegrees (m_attachment_rotation);
m_matrixnode->updateAbsolutePosition ();
}
if (m_is_local_player) {
LocalPlayer *player = m_env->getLocalPlayer ();
player->isAttached = true ;
}
}
if (m_is_local_player) {
LocalPlayer *player = m_env->getLocalPlayer ();
player->isAttached = parent;
player->parent = parent;
}
}
Expand Down
Expand Up
@@ -1488,31 +1524,15 @@ void GenericCAO::processMessage(const std::string &data)
updateBonePosition ();
} else if (cmd == GENERIC_CMD_ATTACH_TO) {
u16 parent_id = readS16 (is);
u16 &old_parent_id = m_env->attachement_parent_ids [getId ()];
if (parent_id != old_parent_id) {
if (GenericCAO *old_parent = m_env->getGenericCAO (old_parent_id)) {
old_parent->m_children .erase (std::remove (
m_children.begin (), m_children.end (),
getId ()), m_children.end ());
}
if (GenericCAO *new_parent = m_env->getGenericCAO (parent_id))
new_parent->m_children .push_back (getId ());
old_parent_id = parent_id;
}
std::string bone = deSerializeString (is);
v3f position = readV3F32 (is);
v3f rotation = readV3F32 (is);
m_attachment_bone = deSerializeString (is);
m_attachment_position = readV3F32 (is);
m_attachment_rotation = readV3F32 (is);
setAttachment (parent_id, bone, position, rotation);
// localplayer itself can't be attached to localplayer
if (!m_is_local_player) {
m_attached_to_local = getParent () != NULL && getParent ()->isLocalPlayer ();
// Objects attached to the local player should be hidden by default
if (!m_is_local_player)
m_is_visible = !m_attached_to_local;
}
updateAttachments ();
} else if (cmd == GENERIC_CMD_PUNCHED) {
u16 result_hp = readU16 (is);
Expand All
@@ -1539,6 +1559,12 @@ void GenericCAO::processMessage(const std::string &data)
m_reset_textures_timer += 0.05 * damage;
updateTextures (m_current_texture_modifier + " ^[brighten" );
}
} else {
// Same as 'Server::DiePlayer'
clearParentAttachment ();
// Same as 'ObjectRef::l_remove'
if (!m_is_player)
clearChildAttachments ();
}
} else if (cmd == GENERIC_CMD_UPDATE_ARMOR_GROUPS) {
m_armor_groups.clear ();
Expand All
@@ -1561,13 +1587,10 @@ void GenericCAO::processMessage(const std::string &data)
}
} else if (cmd == GENERIC_CMD_SPAWN_INFANT) {
u16 child_id = readU16 (is);
u8 type = readU8 (is);
u8 type = readU8 (is); // maybe this will be useful later
(void )type;
if (GenericCAO *childobj = m_env->getGenericCAO (child_id)) {
childobj->processInitData (deSerializeLongString (is));
} else {
m_env->addActiveObject (child_id, type, deSerializeLongString (is));
}
addAttachmentChild (child_id);
} else {
warningstream << FUNCTION_NAME
<< " : unknown command or outdated client \" "
Expand Down