// Only set at initialization
std::string m_name;
bool m_is_player;
- bool m_is_local_player; // determined locally
+ bool m_is_local_player;
int m_id;
// Property-ish things
ObjectProperties m_prop;
bool m_visuals_expired;
float m_step_distance_counter;
u8 m_last_light;
+ bool m_is_visible;
public:
GenericCAO(IGameDef *gamedef, ClientEnvironment *env):
m_reset_textures_timer(-1),
m_visuals_expired(false),
m_step_distance_counter(0),
- m_last_light(255)
+ m_last_light(255),
+ m_is_visible(false)
{
if(gamedef == NULL)
ClientActiveObject::registerType(getType(), create);
}
core::aabbox3d<f32>* getSelectionBox()
{
- if(!m_prop.is_visible || m_is_local_player)
+ if(!m_prop.is_visible || !m_is_visible || m_is_local_player)
return NULL;
return &m_selection_box;
}
return pos_translator.vect_show;
}
+ scene::IMeshSceneNode *getMeshSceneNode()
+ {
+ return m_meshnode;
+ }
+
+ scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode()
+ {
+ return m_animated_meshnode;
+ }
+
+ scene::IBillboardSceneNode *getSpriteSceneNode()
+ {
+ return m_spritenode;
+ }
+
+ bool isPlayer()
+ {
+ return m_is_player;
+ }
+
+ bool isLocalPlayer()
+ {
+ return m_is_local_player;
+ }
+
void removeFromScene()
{
if(m_meshnode){
void updateLight(u8 light_at_pos)
{
- bool is_visible = (m_hp != 0);
+ // Objects attached to the local player should always be hidden
+ if(m_attachment_parent != NULL && m_attachment_parent->isLocalPlayer())
+ m_is_visible = false;
+ else
+ m_is_visible = (m_hp != 0);
u8 li = decode_light(light_at_pos);
+
if(li != m_last_light){
m_last_light = li;
video::SColor color(255,li,li,li);
if(m_meshnode){
setMeshColor(m_meshnode->getMesh(), color);
- m_meshnode->setVisible(is_visible);
+ m_meshnode->setVisible(m_is_visible);
}
if(m_animated_meshnode){
setMeshColor(m_animated_meshnode->getMesh(), color);
- m_animated_meshnode->setVisible(is_visible);
+ m_animated_meshnode->setVisible(m_is_visible);
}
if(m_spritenode){
m_spritenode->setColor(color);
- m_spritenode->setVisible(is_visible);
+ m_spritenode->setVisible(m_is_visible);
}
}
}
addToScene(m_smgr, m_gamedef->tsrc(), m_irr);
updateAnimations();
updateBonePosRot();
+ updateAttachments();
}
if(m_attachment_parent == NULL) // Attachments should be glued to their parent by Irrlicht
m_yaw += dtime * m_prop.automatic_rotate * 180 / M_PI;
updateNodePos();
}
+
+ if(m_animated_meshnode)
+ errorstream<<"Attachment position: "<<m_animated_meshnode->getPosition().X<<","<<m_animated_meshnode->getPosition().Y<<","<<m_animated_meshnode->getPosition().Z<<std::endl;
}
void updateTexturePos()
//Useful links:
// http://irrlicht.sourceforge.net/forum/viewtopic.php?t=7514
// http://www.irrlicht3d.org/wiki/index.php?n=Main.HowToUseTheNewAnimationSystem
+ // http://gamedev.stackexchange.com/questions/27363/finding-the-endpoint-of-a-named-bone-in-irrlicht
// Irrlicht documentation: http://irrlicht.sourceforge.net/docu/
+
+ if (m_attachment_parent != NULL && !m_attachment_parent->isLocalPlayer())
+ {
+ // REMAINING ATTACHMENT ISSUES:
+ // The code below should cause the child to get attached, but for some reason it's not working
+ // A debug print confirms both position and absolute position are set accordingly, but the object still shows at origin 0,0,0
+
+ scene::IMeshSceneNode *parent_mesh = NULL;
+ if(m_attachment_parent->getMeshSceneNode())
+ parent_mesh = m_attachment_parent->getMeshSceneNode();
+ scene::IAnimatedMeshSceneNode *parent_animated_mesh = NULL;
+ if(m_attachment_parent->getAnimatedMeshSceneNode())
+ parent_animated_mesh = m_attachment_parent->getAnimatedMeshSceneNode();
+ scene::IBillboardSceneNode *parent_sprite = NULL;
+ if(m_attachment_parent->getSpriteSceneNode())
+ parent_sprite = m_attachment_parent->getSpriteSceneNode();
+
+ scene::IBoneSceneNode *parent_bone = NULL;
+ if(parent_animated_mesh && m_attachment_bone != "")
+ parent_bone = parent_animated_mesh->getJointNode(m_attachment_bone.c_str());
+ if(!parent_bone) // Should be false if the bone doesn't exist on the mesh
+ parent_bone = NULL;
+
+ // TODO: Perhaps use polymorphism here to save code duplication
+ if(m_meshnode){
+ if(parent_bone){
+ m_meshnode->setPosition(parent_bone->getPosition());
+ m_meshnode->setRotation(parent_bone->getRotation());
+ m_meshnode->updateAbsolutePosition();
+ //m_meshnode->setParent(parent_bone);
+ }
+ else
+ {
+ if(parent_mesh){
+ m_meshnode->setPosition(parent_mesh->getPosition());
+ m_meshnode->setRotation(parent_mesh->getRotation());
+ m_meshnode->updateAbsolutePosition();
+ //m_meshnode->setParent(parent_mesh);
+ }
+ else if(parent_animated_mesh){
+ m_meshnode->setPosition(parent_animated_mesh->getPosition());
+ m_meshnode->setRotation(parent_animated_mesh->getRotation());
+ m_meshnode->updateAbsolutePosition();
+ //m_meshnode->setParent(parent_animated_mesh);
+ }
+ else if(parent_sprite){
+ m_meshnode->setPosition(parent_sprite->getPosition());
+ m_meshnode->setRotation(parent_sprite->getRotation());
+ m_meshnode->updateAbsolutePosition();
+ //m_meshnode->setParent(parent_sprite);
+ }
+ }
+ }
+ if(m_animated_meshnode){
+ if(parent_bone){
+ m_animated_meshnode->setPosition(parent_bone->getPosition());
+ m_animated_meshnode->setRotation(parent_bone->getRotation());
+ m_animated_meshnode->updateAbsolutePosition();
+ //m_animated_meshnode->setParent(parent_bone);
+ }
+ else
+ {
+ if(parent_mesh){
+ m_animated_meshnode->setPosition(parent_mesh->getPosition());
+ m_animated_meshnode->setRotation(parent_mesh->getRotation());
+ m_animated_meshnode->updateAbsolutePosition();
+ //m_animated_meshnode->setParent(parent_mesh);
+ }
+ else if(parent_animated_mesh){
+ m_animated_meshnode->setPosition(parent_animated_mesh->getPosition());
+ m_animated_meshnode->setRotation(parent_animated_mesh->getRotation());
+ m_animated_meshnode->updateAbsolutePosition();
+ //m_animated_meshnode->setParent(parent_animated_mesh);
+ }
+ else if(parent_sprite){
+ m_animated_meshnode->setPosition(parent_sprite->getPosition());
+ m_animated_meshnode->setRotation(parent_sprite->getRotation());
+ m_animated_meshnode->updateAbsolutePosition();
+ //m_animated_meshnode->setParent(parent_sprite);
+ }
+ }
+ }
+ if(m_spritenode){
+ if(parent_bone){
+ m_spritenode->setPosition(parent_bone->getPosition());
+ m_spritenode->setRotation(parent_bone->getRotation());
+ m_spritenode->updateAbsolutePosition();
+ //m_spritenode->setParent(parent_bone);
+ }
+ else
+ {
+ if(parent_mesh){
+ m_spritenode->setPosition(parent_mesh->getPosition());
+ m_spritenode->setRotation(parent_mesh->getRotation());
+ m_spritenode->updateAbsolutePosition();
+ //m_spritenode->setParent(parent_mesh);
+ }
+ else if(parent_animated_mesh){
+ m_spritenode->setPosition(parent_animated_mesh->getPosition());
+ m_spritenode->setRotation(parent_animated_mesh->getRotation());
+ m_spritenode->updateAbsolutePosition();
+ //m_spritenode->setParent(parent_animated_mesh);
+ }
+ else if(parent_sprite){
+ m_spritenode->setPosition(parent_sprite->getPosition());
+ m_spritenode->setRotation(parent_sprite->getRotation());
+ m_spritenode->updateAbsolutePosition();
+ //m_spritenode->setParent(parent_sprite);
+ }
+ }
+ }
+ }
}
void processMessage(const std::string &data)
}
else if(cmd == GENERIC_CMD_SET_ATTACHMENT)
{
- ClientActiveObject *obj;
int parent_id = readS16(is);
- if(parent_id > 0)
- obj = m_env->getActiveObject(parent_id);
- else
+ ClientActiveObject *obj = m_env->getActiveObject(parent_id);
+ if(!parent_id || !obj)
obj = NULL;
m_attachment_parent = obj;
m_attachment_bone = deSerializeString(is);
m_last_sent_position_timer += dtime;
+ // Each frame, parent position is copied if the object is attached, otherwise it's calculated normally
+ // If the object gets detached this comes into effect automatically from the last known origin
if(m_parent != NULL)
{
- // REMAINING ATTACHMENT ISSUES:
- // This is causing a segmentation fault, investigate why!
- //m_base_position = m_parent->getBasePosition();
+ v3f pos = m_parent->getBasePosition();
+ m_base_position = pos;
m_velocity = v3f(0,0,0);
m_acceleration = v3f(0,0,0);
}
if(send_recommended == false)
return;
-
- // TODO: force send when acceleration changes enough?
- float minchange = 0.2*BS;
- if(m_last_sent_position_timer > 1.0){
- minchange = 0.01*BS;
- } else if(m_last_sent_position_timer > 0.2){
- minchange = 0.05*BS;
- }
- float move_d = m_base_position.getDistanceFrom(m_last_sent_position);
- move_d += m_last_sent_move_precision;
- float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity);
- if(move_d > minchange || vel_d > minchange ||
- fabs(m_yaw - m_last_sent_yaw) > 1.0){
- sendPosition(true, false);
+
+ if(m_parent != NULL)
+ {
+ // TODO: force send when acceleration changes enough?
+ float minchange = 0.2*BS;
+ if(m_last_sent_position_timer > 1.0){
+ minchange = 0.01*BS;
+ } else if(m_last_sent_position_timer > 0.2){
+ minchange = 0.05*BS;
+ }
+ float move_d = m_base_position.getDistanceFrom(m_last_sent_position);
+ move_d += m_last_sent_move_precision;
+ float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity);
+ if(move_d > minchange || vel_d > minchange ||
+ fabs(m_yaw - m_last_sent_yaw) > 1.0){
+ sendPosition(true, false);
+ }
}
if(m_armor_groups_sent == false){
{
// 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. Attachments
- // are still sent to clients at an interval so players would see them following the parent
- // instead of sticking to it, plus we can't read and attach to skeletal bones.
+ // are still sent to clients at an interval so players might see them lagging, plus we can't
+ // read and attach to skeletal bones.
// If we just attach on the client, the server still sees the child at its original location.
- // This can break some things, so we also give the server the most accurate representation
- // even if players will only see the client changes since they override server-sent position.
+ // This breaks some things so we also give the server the most accurate representation
+ // even if players only see the client changes.
// Server attachment:
m_parent = parent;
void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
{
+ // If the object is attached client-side, don't waste bandwidth sending its position to clients
if(m_parent != NULL)
return;
}
void PlayerSAO::step(float dtime, bool send_recommended)
-{
+{
if(!m_properties_sent)
{
m_properties_sent = true;
m_time_from_last_punch += dtime;
m_nocheat_dig_time += dtime;
- if(m_parent == NULL)
+ // Each frame, parent position is copied if the object is attached, otherwise it's calculated normally
+ // If the object gets detached this comes into effect automatically from the last known origin
+ if(m_parent != NULL)
+ {
+ v3f pos = m_parent->getBasePosition();
+ m_last_good_position = pos;
+ m_last_good_position_age = 0;
+ m_player->setPosition(pos);
+ }
+ else
{
if(m_is_singleplayer || g_settings->getBool("disable_anticheat"))
{
if(send_recommended == false)
return;
- // If the object is attached client-side, don't waste bandwidth and send its position to clients
+ // If the object is attached client-side, don't waste bandwidth sending its position to clients
if(m_position_not_sent && m_parent == NULL)
{
m_position_not_sent = false;
float update_interval = m_env->getSendRecommendedInterval();
v3f pos;
- // REMAINING ATTACHMENT ISSUES:
- // This is causing a segmentation fault, investigate why!
- if(m_parent != NULL)
+ if(m_parent != NULL) // Just in case we ever do send attachment position too
pos = m_parent->getBasePosition();
else
pos = m_player->getPosition() + v3f(0,BS*1,0);
void PlayerSAO::setBasePosition(const v3f &position)
{
- if(m_parent != NULL)
- return;
+ // This needs to be ran for attachments too
ServerActiveObject::setBasePosition(position);
m_position_not_sent = true;
}
{
// 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. Attachments
- // are still sent to clients at an interval so players would see them following the parent
- // instead of sticking to it, plus we can't read and attach to skeletal bones.
+ // are still sent to clients at an interval so players might see them lagging, plus we can't
+ // read and attach to skeletal bones.
// If we just attach on the client, the server still sees the child at its original location.
- // This can break some things, so we also give the server the most accurate representation
- // even if players will only see the client changes since they override server-sent position.
+ // This breaks some things so we also give the server the most accurate representation
+ // even if players only see the client changes.
// Server attachment:
m_parent = parent;