aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/lua_api.txt2
-rw-r--r--src/content_cao.cpp123
-rw-r--r--src/content_sao.cpp102
-rw-r--r--src/content_sao.h14
-rw-r--r--src/guiFormSpecMenu.cpp2
-rw-r--r--src/localplayer.cpp7
-rw-r--r--src/localplayer.h4
-rw-r--r--src/scriptapi.cpp17
-rw-r--r--src/server.cpp4
-rw-r--r--src/serverobject.h2
10 files changed, 171 insertions, 106 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index cb84b5459..45ee7648b 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -1104,6 +1104,8 @@ methods:
- set_wielded_item(item): replaces the wielded item, returns true if successful
- set_armor_groups({group1=rating, group2=rating, ...})
- set_animations({x=1,y=1}, frame_speed=15, frame_blend=0)
+- set_attachment(parent, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
+- set_detachment()
- set_bone_posrot("", {x=0,y=0,z=0}, {x=0,y=0,z=0})
- set_properties(object property table)
LuaEntitySAO-only: (no-op for other objects)
diff --git a/src/content_cao.cpp b/src/content_cao.cpp
index c2cce3d58..821862c9b 100644
--- a/src/content_cao.cpp
+++ b/src/content_cao.cpp
@@ -768,50 +768,26 @@ public:
void removeFromScene(bool permanent)
{
- // bool permanent should be true when removing the object permanently and false when it's only refreshed (and comes back in a few frames)
-
- // If this object is being permanently removed, delete it from the attachments list
- if(permanent)
+ if(permanent) // Should be true when removing the object permanently and false when refreshing (eg: updating visuals)
{
+ // Detach this object's children
for(std::vector<core::vector2d<int> >::iterator ii = attachment_list.begin(); ii != attachment_list.end(); ii++)
{
- if(ii->X == this->getId()) // This is the ID of our object
+ if(ii->Y == this->getId()) // Is a child of our object
{
- attachment_list.erase(ii);
- break;
+ ii->Y = 0;
+ ClientActiveObject *obj = m_env->getActiveObject(ii->X); // Get the object of the child
+ if(obj)
+ obj->updateParent();
}
}
- }
-
- // If this object is being removed, either permanently or just to refresh it, then all
- // objects attached to it must be unparented else Irrlicht causes a segmentation fault.
- for(std::vector<core::vector2d<int> >::iterator ii = attachment_list.begin(); ii != attachment_list.end(); ii++)
- {
- if(ii->Y == this->getId()) // This is a child of our parent
+ // Delete this object from the attachments list
+ for(std::vector<core::vector2d<int> >::iterator ii = attachment_list.begin(); ii != attachment_list.end(); ii++)
{
- ClientActiveObject *obj = m_env->getActiveObject(ii->X); // Get the object of the child
- if(obj)
+ if(ii->X == this->getId()) // Is our object
{
- if(permanent)
- {
- // The parent is being permanently removed, so the child stays detached
- ii->Y = 0;
- obj->updateParent();
- }
- else
- {
- // The parent is being refreshed, detach our child enough to avoid bad memory reads
- // This only stays into effect for a few frames, as addToScene will parent its children back
- scene::IMeshSceneNode *m_child_meshnode = obj->getMeshSceneNode();
- scene::IAnimatedMeshSceneNode *m_child_animated_meshnode = obj->getAnimatedMeshSceneNode();
- scene::IBillboardSceneNode *m_child_spritenode = obj->getSpriteSceneNode();
- if(m_child_meshnode)
- m_child_meshnode->setParent(m_smgr->getRootSceneNode());
- if(m_child_animated_meshnode)
- m_child_animated_meshnode->setParent(m_smgr->getRootSceneNode());
- if(m_child_spritenode)
- m_child_spritenode->setParent(m_smgr->getRootSceneNode());
- }
+ attachment_list.erase(ii);
+ break;
}
}
}
@@ -836,18 +812,6 @@ public:
m_smgr = smgr;
m_irr = irr;
- // If this object has attachments and is being re-added after having been refreshed, parent its children back.
- // The parent ID for this child hasn't been changed in attachment_list, so just update its attachments.
- for(std::vector<core::vector2d<int> >::iterator ii = attachment_list.begin(); ii != attachment_list.end(); ii++)
- {
- if(ii->Y == this->getId()) // This is a child of our parent
- {
- ClientActiveObject *obj = m_env->getActiveObject(ii->X); // Get the object of the child
- if(obj)
- obj->updateParent();
- }
- }
-
if(m_meshnode != NULL || m_animated_meshnode != NULL || m_spritenode != NULL)
return;
@@ -1074,14 +1038,45 @@ public:
if(m_visuals_expired && m_smgr && m_irr){
m_visuals_expired = false;
+
+ // Attachments, part 1: All attached objects must be unparented first, or Irrlicht causes a segmentation fault
+ for(std::vector<core::vector2d<int> >::iterator ii = attachment_list.begin(); ii != attachment_list.end(); ii++)
+ {
+ if(ii->Y == this->getId()) // This is a child of our parent
+ {
+ ClientActiveObject *obj = m_env->getActiveObject(ii->X); // Get the object of the child
+ if(obj)
+ {
+ scene::IMeshSceneNode *m_child_meshnode = obj->getMeshSceneNode();
+ scene::IAnimatedMeshSceneNode *m_child_animated_meshnode = obj->getAnimatedMeshSceneNode();
+ scene::IBillboardSceneNode *m_child_spritenode = obj->getSpriteSceneNode();
+ if(m_child_meshnode)
+ m_child_meshnode->setParent(m_smgr->getRootSceneNode());
+ if(m_child_animated_meshnode)
+ m_child_animated_meshnode->setParent(m_smgr->getRootSceneNode());
+ if(m_child_spritenode)
+ m_child_spritenode->setParent(m_smgr->getRootSceneNode());
+ }
+ }
+ }
+
removeFromScene(false);
addToScene(m_smgr, m_gamedef->tsrc(), m_irr);
updateAnimations();
updateBonePosRot();
updateAttachments();
- return;
- }
+ // Attachments, part 2: Now that the parent has been refreshed, put its attachments back
+ for(std::vector<core::vector2d<int> >::iterator ii = attachment_list.begin(); ii != attachment_list.end(); ii++)
+ {
+ if(ii->Y == this->getId()) // This is a child of our parent
+ {
+ ClientActiveObject *obj = m_env->getActiveObject(ii->X); // Get the object of the child
+ if(obj)
+ obj->updateParent();
+ }
+ }
+ }
if(getParent() != NULL) // Attachments should be glued to their parent by Irrlicht
{
// Set these for later
@@ -1093,6 +1088,12 @@ public:
m_position = m_spritenode->getAbsolutePosition();
m_velocity = v3f(0,0,0);
m_acceleration = v3f(0,0,0);
+
+ if(m_is_local_player) // Update local player attachment position
+ {
+ LocalPlayer *player = m_env->getLocalPlayer();
+ player->overridePosition = getParent()->getPosition();
+ }
}
else
{
@@ -1422,6 +1423,11 @@ public:
m_spritenode->setRotation(old_rotation);
m_spritenode->updateAbsolutePosition();
}
+ if(m_is_local_player)
+ {
+ LocalPlayer *player = m_env->getLocalPlayer();
+ player->isAttached = false;
+ }
}
else // Attach
{
@@ -1528,6 +1534,12 @@ public:
}
}
}
+ if(m_is_local_player)
+ {
+ LocalPlayer *player = m_env->getLocalPlayer();
+ player->isAttached = true;
+ player->overridePosition = m_attachment_position;
+ }
}
}
@@ -1557,7 +1569,8 @@ public:
}
else if(cmd == GENERIC_CMD_UPDATE_POSITION)
{
- // Not sent by the server if the object is an attachment
+ // Not sent by the server if this object is an attachment.
+ // We might however get here if the server notices the object being detached before the client.
m_position = readV3F1000(is);
m_velocity = readV3F1000(is);
m_acceleration = readV3F1000(is);
@@ -1567,14 +1580,14 @@ public:
bool is_end_position = readU8(is);
float update_interval = readF1000(is);
- if(getParent() != NULL) // Just in case
- return;
-
// Place us a bit higher if we're physical, to not sink into
// the ground due to sucky collision detection...
if(m_prop.physical)
m_position += v3f(0,0.002,0);
-
+
+ if(getParent() != NULL) // Just in case
+ return;
+
if(do_interpolate){
if(!m_prop.physical)
pos_translator.update(m_position, is_end_position, update_interval);
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index c906383af..963e4b43a 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -218,7 +218,6 @@ public:
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
{
- // TODO: We shouldn't be sending this when the object is attached, but we can't check m_parent here
setBasePosition(pos_f);
m_last_sent_position = pos_f;
@@ -387,7 +386,6 @@ void LuaEntitySAO::addedToEnvironment(u32 dtime_s)
// Create entity from name
lua_State *L = m_env->getLua();
m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str());
- m_parent = NULL;
if(m_registered){
// Get properties
@@ -434,6 +432,17 @@ ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos,
return sao;
}
+bool LuaEntitySAO::isAttached()
+{
+ if(!m_attachment_parent_id)
+ return false;
+ // Check if the parent still exists
+ ServerActiveObject *obj = m_env->getActiveObject(m_attachment_parent_id);
+ if(obj)
+ return true;
+ return false;
+}
+
void LuaEntitySAO::step(float dtime, bool send_recommended)
{
if(!m_properties_sent)
@@ -445,13 +454,23 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
m_messages_out.push_back(aom);
}
+ // If attached, check that our parent is still there. If it isn't, detach.
+ if(m_attachment_parent_id && !isAttached())
+ {
+ m_attachment_parent_id = 0;
+ m_attachment_bone = "";
+ m_attachment_position = v3f(0,0,0);
+ m_attachment_rotation = v3f(0,0,0);
+ sendPosition(false, true);
+ }
+
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)
+ if(isAttached())
{
- v3f pos = m_parent->getBasePosition();
+ v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition();
m_base_position = pos;
m_velocity = v3f(0,0,0);
m_acceleration = v3f(0,0,0);
@@ -491,7 +510,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
if(send_recommended == false)
return;
- if(m_parent != NULL)
+ if(!isAttached())
{
// TODO: force send when acceleration changes enough?
float minchange = 0.2*BS;
@@ -608,7 +627,7 @@ int LuaEntitySAO::punch(v3f dir,
}
// It's best that attachments cannot be punched
- if(m_parent != NULL)
+ if(isAttached())
return 0;
ItemStack *punchitem = NULL;
@@ -660,7 +679,7 @@ void LuaEntitySAO::rightClick(ServerActiveObject *clicker)
void LuaEntitySAO::setPos(v3f pos)
{
- if(m_parent != NULL)
+ if(isAttached())
return;
m_base_position = pos;
sendPosition(false, true);
@@ -668,7 +687,7 @@ void LuaEntitySAO::setPos(v3f pos)
void LuaEntitySAO::moveTo(v3f pos, bool continuous)
{
- if(m_parent != NULL)
+ if(isAttached())
return;
m_base_position = pos;
if(!continuous)
@@ -722,7 +741,7 @@ void LuaEntitySAO::setBonePosRot(std::string bone, v3f position, v3f rotation)
m_animations_bone_sent = false;
}
-void LuaEntitySAO::setAttachment(ServerActiveObject *parent, std::string bone, v3f position, v3f rotation)
+void LuaEntitySAO::setAttachment(int parent_id, std::string bone, v3f position, v3f rotation)
{
// 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
@@ -732,11 +751,7 @@ void LuaEntitySAO::setAttachment(ServerActiveObject *parent, std::string bone, v
// 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;
-
- // Client attachment:
- m_attachment_parent_id = parent->getId();
+ m_attachment_parent_id = parent_id;
m_attachment_bone = bone;
m_attachment_position = position;
m_attachment_rotation = rotation;
@@ -818,7 +833,7 @@ std::string LuaEntitySAO::getPropertyPacket()
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)
+ if(isAttached())
return;
m_last_sent_move_precision = m_base_position.getDistanceFrom(
@@ -872,7 +887,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
m_animations_bone_sent(false),
m_attachment_sent(false),
// public
- m_teleported(false),
+ m_moved(false),
m_inventory_not_sent(false),
m_hp_not_sent(false),
m_wielded_item_not_sent(false)
@@ -919,7 +934,6 @@ void PlayerSAO::addedToEnvironment(u32 dtime_s)
{
ServerActiveObject::addedToEnvironment(dtime_s);
ServerActiveObject::setBasePosition(m_player->getPosition());
- m_parent = NULL;
m_player->setPlayerSAO(this);
m_player->peer_id = m_peer_id;
m_last_good_position = m_player->getPosition();
@@ -979,6 +993,17 @@ std::string PlayerSAO::getStaticData()
return "";
}
+bool PlayerSAO::isAttached()
+{
+ if(!m_attachment_parent_id)
+ return false;
+ // Check if the parent still exists
+ ServerActiveObject *obj = m_env->getActiveObject(m_attachment_parent_id);
+ if(obj)
+ return true;
+ return false;
+}
+
void PlayerSAO::step(float dtime, bool send_recommended)
{
if(!m_properties_sent)
@@ -990,14 +1015,25 @@ void PlayerSAO::step(float dtime, bool send_recommended)
m_messages_out.push_back(aom);
}
+ // If attached, check that our parent is still there. If it isn't, detach.
+ if(m_attachment_parent_id && !isAttached())
+ {
+ m_attachment_parent_id = 0;
+ m_attachment_bone = "";
+ m_attachment_position = v3f(0,0,0);
+ m_attachment_rotation = v3f(0,0,0);
+ m_player->setPosition(m_last_good_position);
+ m_moved = true;
+ }
+
m_time_from_last_punch += dtime;
m_nocheat_dig_time += 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)
+ if(isAttached())
{
- v3f pos = m_parent->getBasePosition();
+ v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition();
m_last_good_position = pos;
m_last_good_position_age = 0;
m_player->setPosition(pos);
@@ -1053,7 +1089,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
<<" moved too fast; resetting position"
<<std::endl;
m_player->setPosition(m_last_good_position);
- m_teleported = true;
+ m_moved = true;
}
m_last_good_position_age = 0;
}
@@ -1064,13 +1100,13 @@ void PlayerSAO::step(float dtime, bool send_recommended)
return;
// If the object is attached client-side, don't waste bandwidth sending its position to clients
- if(m_position_not_sent && m_parent == NULL)
+ if(m_position_not_sent && !isAttached())
{
m_position_not_sent = false;
float update_interval = m_env->getSendRecommendedInterval();
v3f pos;
- if(m_parent != NULL) // Just in case we ever do send attachment position too
- pos = m_parent->getBasePosition();
+ if(isAttached()) // Just in case we ever do send attachment position too
+ pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition();
else
pos = m_player->getPosition() + v3f(0,BS*1,0);
std::string str = gob_cmd_update_position(
@@ -1138,26 +1174,26 @@ void PlayerSAO::setBasePosition(const v3f &position)
void PlayerSAO::setPos(v3f pos)
{
- if(m_parent != NULL)
+ if(isAttached())
return;
m_player->setPosition(pos);
// Movement caused by this command is always valid
m_last_good_position = pos;
m_last_good_position_age = 0;
// Force position change on client
- m_teleported = true;
+ m_moved = true;
}
void PlayerSAO::moveTo(v3f pos, bool continuous)
{
- if(m_parent != NULL)
+ if(isAttached())
return;
m_player->setPosition(pos);
// Movement caused by this command is always valid
m_last_good_position = pos;
m_last_good_position_age = 0;
// Force position change on client
- m_teleported = true;
+ m_moved = true;
}
int PlayerSAO::punch(v3f dir,
@@ -1166,7 +1202,7 @@ int PlayerSAO::punch(v3f dir,
float time_from_last_punch)
{
// It's best that attachments cannot be punched
- if(m_parent != NULL)
+ if(isAttached())
return 0;
if(!toolcap)
@@ -1266,7 +1302,7 @@ void PlayerSAO::setBonePosRot(std::string bone, v3f position, v3f rotation)
m_animations_bone_sent = false;
}
-void PlayerSAO::setAttachment(ServerActiveObject *parent, std::string bone, v3f position, v3f rotation)
+void PlayerSAO::setAttachment(int parent_id, std::string bone, v3f position, v3f rotation)
{
// 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
@@ -1276,11 +1312,7 @@ void PlayerSAO::setAttachment(ServerActiveObject *parent, std::string bone, v3f
// 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;
-
- // Client attachment:
- m_attachment_parent_id = parent->getId();
+ m_attachment_parent_id = parent_id;
m_attachment_bone = bone;
m_attachment_position = position;
m_attachment_rotation = rotation;
diff --git a/src/content_sao.h b/src/content_sao.h
index 9e79ec0e0..f6e0bac5b 100644
--- a/src/content_sao.h
+++ b/src/content_sao.h
@@ -46,6 +46,7 @@ public:
virtual void addedToEnvironment(u32 dtime_s);
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data);
+ bool isAttached();
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
@@ -63,7 +64,7 @@ public:
void setArmorGroups(const ItemGroupList &armor_groups);
void setAnimations(v2f frames, float frame_speed, float frame_blend);
void setBonePosRot(std::string bone, v3f position, v3f rotation);
- void setAttachment(ServerActiveObject *parent, std::string bone, v3f position, v3f rotation);
+ void setAttachment(int parent_id, std::string bone, v3f position, v3f rotation);
ObjectProperties* accessObjectProperties();
void notifyObjectPropertiesModified();
/* LuaEntitySAO-specific */
@@ -107,8 +108,7 @@ private:
std::map<std::string, core::vector2d<v3f> > m_animation_bone;
bool m_animations_bone_sent;
-
- ServerActiveObject *m_parent;
+
int m_attachment_parent_id;
std::string m_attachment_bone;
v3f m_attachment_position;
@@ -142,6 +142,7 @@ public:
bool unlimitedTransferDistance() const;
std::string getClientInitializationData();
std::string getStaticData();
+ bool isAttached();
void step(float dtime, bool send_recommended);
void setBasePosition(const v3f &position);
void setPos(v3f pos);
@@ -162,7 +163,7 @@ public:
void setArmorGroups(const ItemGroupList &armor_groups);
void setAnimations(v2f frames, float frame_speed, float frame_blend);
void setBonePosRot(std::string bone, v3f position, v3f rotation);
- void setAttachment(ServerActiveObject *parent, std::string bone, v3f position, v3f rotation);
+ void setAttachment(int parent_id, std::string bone, v3f position, v3f rotation);
ObjectProperties* accessObjectProperties();
void notifyObjectPropertiesModified();
@@ -266,8 +267,7 @@ private:
std::map<std::string, core::vector2d<v3f> > m_animation_bone; // stores position and rotation for each bone name
bool m_animations_bone_sent;
-
- ServerActiveObject *m_parent;
+
int m_attachment_parent_id;
std::string m_attachment_bone;
v3f m_attachment_position;
@@ -276,7 +276,7 @@ private:
public:
// Some flags used by Server
- bool m_teleported;
+ bool m_moved;
bool m_inventory_not_sent;
bool m_hp_not_sent;
bool m_wielded_item_not_sent;
diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp
index 4db020c11..7f638830f 100644
--- a/src/guiFormSpecMenu.cpp
+++ b/src/guiFormSpecMenu.cpp
@@ -714,7 +714,6 @@ void GUIFormSpecMenu::drawMenu()
Draw backgrounds
*/
for(u32 i=0; i<m_backgrounds.size(); i++)
- {
const ImageDrawSpec &spec = m_backgrounds[i];
video::ITexture *texture =
m_gamedef->tsrc()->getTextureRaw(spec.name);
@@ -728,7 +727,6 @@ void GUIFormSpecMenu::drawMenu()
core::rect<s32>(core::position2d<s32>(0,0),
core::dimension2di(texture->getOriginalSize())),
NULL/*&AbsoluteClippingRect*/, colors, true);
- }
/*
Draw images
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 4b5e53fea..ecfa4467c 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -53,6 +53,13 @@ LocalPlayer::~LocalPlayer()
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
core::list<CollisionInfo> *collision_info)
{
+ // Copy parent position if local player is attached
+ if(isAttached)
+ {
+ setPosition(overridePosition);
+ return;
+ }
+
INodeDefManager *nodemgr = m_gamedef->ndef();
v3f position = getPosition();
diff --git a/src/localplayer.h b/src/localplayer.h
index fb57e6538..b613fdb0f 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -79,6 +79,10 @@ public:
{
return true;
}
+
+ bool isAttached;
+
+ v3f overridePosition;
void move(f32 dtime, Map &map, f32 pos_max_d,
core::list<CollisionInfo> *collision_info);
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index 3c505c881..9fd55b2e3 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -2723,7 +2723,6 @@ private:
ServerActiveObject *co = getobject(ref);
if(co == NULL) return 0;
// Do it
-
v2f frames = v2f(1, 1);
if(!lua_isnil(L, 2))
frames = read_v2f(L, 2);
@@ -2744,7 +2743,6 @@ private:
ServerActiveObject *co = getobject(ref);
if(co == NULL) return 0;
// Do it
-
std::string bone = "";
if(!lua_isnil(L, 2))
bone = lua_tostring(L, 2);
@@ -2767,6 +2765,7 @@ private:
ServerActiveObject *parent = getobject(parent_ref);
if(co == NULL) return 0;
if(parent == NULL) return 0;
+ // Do it
std::string bone = "";
if(!lua_isnil(L, 3))
bone = lua_tostring(L, 3);
@@ -2776,9 +2775,18 @@ private:
v3f rotation = v3f(0, 0, 0);
if(!lua_isnil(L, 5))
rotation = read_v3f(L, 5);
- // Do it
+ co->setAttachment(parent->getId(), bone, position, rotation);
+ return 0;
+ }
- co->setAttachment(parent, bone, position, rotation);
+ // set_detachment(self)
+ static int l_set_detachment(lua_State *L)
+ {
+ ObjectRef *ref = checkobject(L, 1);
+ ServerActiveObject *co = getobject(ref);
+ if(co == NULL) return 0;
+ // Do it
+ co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0));
return 0;
}
@@ -3099,6 +3107,7 @@ const luaL_reg ObjectRef::methods[] = {
method(ObjectRef, set_animations),
method(ObjectRef, set_bone_posrot),
method(ObjectRef, set_attachment),
+ method(ObjectRef, set_detachment),
method(ObjectRef, set_properties),
// LuaEntitySAO-only
method(ObjectRef, setvelocity),
diff --git a/src/server.cpp b/src/server.cpp
index 930938ecb..1a401bb62 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -1371,9 +1371,9 @@ void Server::AsyncRunStep()
/*
Send player inventories and HPs if necessary
*/
- if(playersao->m_teleported){
+ if(playersao->m_moved){
SendMovePlayer(client->peer_id);
- playersao->m_teleported = false;
+ playersao->m_moved = false;
}
if(playersao->m_inventory_not_sent){
UpdateCrafting(client->peer_id);
diff --git a/src/serverobject.h b/src/serverobject.h
index 3dcb99552..a0886ed1e 100644
--- a/src/serverobject.h
+++ b/src/serverobject.h
@@ -156,7 +156,7 @@ public:
{}
virtual void setBonePosRot(std::string bone, v3f position, v3f rotation)
{}
- virtual void setAttachment(ServerActiveObject *parent, std::string bone, v3f position, v3f rotation)
+ virtual void setAttachment(int parent_id, std::string bone, v3f position, v3f rotation)
{}
virtual ObjectProperties* accessObjectProperties()
{ return NULL; }