summaryrefslogtreecommitdiff
path: root/src/content_sao.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/content_sao.cpp')
-rw-r--r--src/content_sao.cpp228
1 files changed, 146 insertions, 82 deletions
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index b23d287f4..7787e33fb 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -218,6 +218,7 @@ 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;
@@ -383,6 +384,7 @@ 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
@@ -442,28 +444,39 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
m_last_sent_position_timer += dtime;
- if(m_prop.physical){
- core::aabbox3d<f32> box = m_prop.collisionbox;
- box.MinEdge *= BS;
- box.MaxEdge *= BS;
- collisionMoveResult moveresult;
- f32 pos_max_d = BS*0.25; // Distance per iteration
- f32 stepheight = 0; // Maximum climbable step height
- v3f p_pos = m_base_position;
- v3f p_velocity = m_velocity;
- v3f p_acceleration = m_acceleration;
- IGameDef *gamedef = m_env->getGameDef();
- moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
- pos_max_d, box, stepheight, dtime,
- p_pos, p_velocity, p_acceleration);
- // Apply results
- m_base_position = p_pos;
- m_velocity = p_velocity;
- m_acceleration = p_acceleration;
- } else {
- m_base_position += dtime * m_velocity + 0.5 * dtime
- * dtime * m_acceleration;
- m_velocity += dtime * m_acceleration;
+ if(m_parent != NULL)
+ {
+ // REMAINING ATTACHMENT ISSUES:
+ // This is causing a segmentation fault, investigate why!
+ //m_base_position = m_parent->getBasePosition();
+ m_velocity = v3f(0,0,0);
+ m_acceleration = v3f(0,0,0);
+ }
+ else
+ {
+ if(m_prop.physical){
+ core::aabbox3d<f32> box = m_prop.collisionbox;
+ box.MinEdge *= BS;
+ box.MaxEdge *= BS;
+ collisionMoveResult moveresult;
+ f32 pos_max_d = BS*0.25; // Distance per iteration
+ f32 stepheight = 0; // Maximum climbable step height
+ v3f p_pos = m_base_position;
+ v3f p_velocity = m_velocity;
+ v3f p_acceleration = m_acceleration;
+ IGameDef *gamedef = m_env->getGameDef();
+ moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
+ pos_max_d, box, stepheight, dtime,
+ p_pos, p_velocity, p_acceleration);
+ // Apply results
+ m_base_position = p_pos;
+ m_velocity = p_velocity;
+ m_acceleration = p_acceleration;
+ } else {
+ m_base_position += dtime * m_velocity + 0.5 * dtime
+ * dtime * m_acceleration;
+ m_velocity += dtime * m_acceleration;
+ }
}
if(m_registered){
@@ -551,6 +564,10 @@ int LuaEntitySAO::punch(v3f dir,
m_removed = true;
return 0;
}
+
+ // It's best that attachments cannot be punched
+ if(m_parent != NULL)
+ return 0;
ItemStack *punchitem = NULL;
ItemStack punchitem_static;
@@ -601,12 +618,16 @@ void LuaEntitySAO::rightClick(ServerActiveObject *clicker)
void LuaEntitySAO::setPos(v3f pos)
{
+ if(m_parent != NULL)
+ return;
m_base_position = pos;
sendPosition(false, true);
}
void LuaEntitySAO::moveTo(v3f pos, bool continuous)
{
+ if(m_parent != NULL)
+ return;
m_base_position = pos;
if(!continuous)
sendPosition(true, true);
@@ -661,14 +682,21 @@ void LuaEntitySAO::setBonePosRot(std::string bone, v3f position, v3f rotation)
m_messages_out.push_back(aom);
}
-// Part of the attachment structure, not used yet!
void LuaEntitySAO::setAttachment(ServerActiveObject *parent, std::string bone, v3f position, v3f rotation)
{
- // Parent should be translated from a ServerActiveObject into something
- // the client will recognize (as a ClientActiveObject) then sent in
- // gob_cmd_set_attachment that way.
+ // 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.
+ // 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.
- std::string str = gob_cmd_set_attachment(); // <- parameters here
+ // Server attachment:
+ m_parent = parent;
+
+ // Client attachment:
+ std::string str = gob_cmd_set_attachment(parent->getId(), bone, position, rotation);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push_back(aom);
@@ -748,6 +776,9 @@ std::string LuaEntitySAO::getPropertyPacket()
void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
{
+ if(m_parent != NULL)
+ return;
+
m_last_sent_move_precision = m_base_position.getDistanceFrom(
m_last_sent_position);
m_last_sent_position_timer = 0;
@@ -843,6 +874,7 @@ 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();
@@ -893,7 +925,7 @@ std::string PlayerSAO::getStaticData()
}
void PlayerSAO::step(float dtime, bool send_recommended)
-{
+{
if(!m_properties_sent)
{
m_properties_sent = true;
@@ -905,71 +937,82 @@ void PlayerSAO::step(float dtime, bool send_recommended)
m_time_from_last_punch += dtime;
m_nocheat_dig_time += dtime;
-
- if(m_is_singleplayer || g_settings->getBool("disable_anticheat"))
- {
- m_last_good_position = m_player->getPosition();
- m_last_good_position_age = 0;
- }
- else
+
+ if(m_parent == NULL)
{
- /*
- Check player movements
-
- NOTE: Actually the server should handle player physics like the
- client does and compare player's position to what is calculated
- on our side. This is required when eg. players fly due to an
- explosion. Altough a node-based alternative might be possible
- too, and much more lightweight.
- */
-
- float player_max_speed = 0;
- float player_max_speed_up = 0;
- if(m_privs.count("fast") != 0){
- // Fast speed
- player_max_speed = BS * 20;
- player_max_speed_up = BS * 20;
- } else {
- // Normal speed
- player_max_speed = BS * 4.0;
- player_max_speed_up = BS * 4.0;
+ if(m_is_singleplayer || g_settings->getBool("disable_anticheat"))
+ {
+ m_last_good_position = m_player->getPosition();
+ m_last_good_position_age = 0;
}
- // Tolerance
- player_max_speed *= 2.5;
- player_max_speed_up *= 2.5;
-
- m_last_good_position_age += dtime;
- if(m_last_good_position_age >= 1.0){
- float age = m_last_good_position_age;
- v3f diff = (m_player->getPosition() - m_last_good_position);
- float d_vert = diff.Y;
- diff.Y = 0;
- float d_horiz = diff.getLength();
- /*infostream<<m_player->getName()<<"'s horizontal speed is "
- <<(d_horiz/age)<<std::endl;*/
- if(d_horiz <= age * player_max_speed &&
- (d_vert < 0 || d_vert < age * player_max_speed_up)){
- m_last_good_position = m_player->getPosition();
+ else
+ {
+ /*
+ Check player movements
+
+ NOTE: Actually the server should handle player physics like the
+ client does and compare player's position to what is calculated
+ on our side. This is required when eg. players fly due to an
+ explosion. Altough a node-based alternative might be possible
+ too, and much more lightweight.
+ */
+
+ float player_max_speed = 0;
+ float player_max_speed_up = 0;
+ if(m_privs.count("fast") != 0){
+ // Fast speed
+ player_max_speed = BS * 20;
+ player_max_speed_up = BS * 20;
} else {
- actionstream<<"Player "<<m_player->getName()
- <<" moved too fast; resetting position"
- <<std::endl;
- m_player->setPosition(m_last_good_position);
- m_teleported = true;
+ // Normal speed
+ player_max_speed = BS * 4.0;
+ player_max_speed_up = BS * 4.0;
+ }
+ // Tolerance
+ player_max_speed *= 2.5;
+ player_max_speed_up *= 2.5;
+
+ m_last_good_position_age += dtime;
+ if(m_last_good_position_age >= 1.0){
+ float age = m_last_good_position_age;
+ v3f diff = (m_player->getPosition() - m_last_good_position);
+ float d_vert = diff.Y;
+ diff.Y = 0;
+ float d_horiz = diff.getLength();
+ /*infostream<<m_player->getName()<<"'s horizontal speed is "
+ <<(d_horiz/age)<<std::endl;*/
+ if(d_horiz <= age * player_max_speed &&
+ (d_vert < 0 || d_vert < age * player_max_speed_up)){
+ m_last_good_position = m_player->getPosition();
+ } else {
+ actionstream<<"Player "<<m_player->getName()
+ <<" moved too fast; resetting position"
+ <<std::endl;
+ m_player->setPosition(m_last_good_position);
+ m_teleported = true;
+ }
+ m_last_good_position_age = 0;
}
- m_last_good_position_age = 0;
}
}
if(send_recommended == false)
return;
- if(m_position_not_sent)
+ // If the object is attached client-side, don't waste bandwidth and send 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)
+ pos = m_parent->getBasePosition();
+ else
+ pos = m_player->getPosition() + v3f(0,BS*1,0);
std::string str = gob_cmd_update_position(
- m_player->getPosition() + v3f(0,BS*1,0),
+ pos,
v3f(0,0,0),
v3f(0,0,0),
m_player->getYaw(),
@@ -1000,12 +1043,16 @@ void PlayerSAO::step(float dtime, bool send_recommended)
void PlayerSAO::setBasePosition(const v3f &position)
{
+ if(m_parent != NULL)
+ return;
ServerActiveObject::setBasePosition(position);
m_position_not_sent = true;
}
void PlayerSAO::setPos(v3f pos)
{
+ if(m_parent != NULL)
+ return;
m_player->setPosition(pos);
// Movement caused by this command is always valid
m_last_good_position = pos;
@@ -1016,6 +1063,8 @@ void PlayerSAO::setPos(v3f pos)
void PlayerSAO::moveTo(v3f pos, bool continuous)
{
+ if(m_parent != NULL)
+ return;
m_player->setPosition(pos);
// Movement caused by this command is always valid
m_last_good_position = pos;
@@ -1029,6 +1078,10 @@ int PlayerSAO::punch(v3f dir,
ServerActiveObject *puncher,
float time_from_last_punch)
{
+ // It's best that attachments cannot be punched
+ if(m_parent != NULL)
+ return 0;
+
if(!toolcap)
return 0;
@@ -1126,10 +1179,21 @@ void PlayerSAO::setBonePosRot(std::string bone, v3f position, v3f rotation)
m_messages_out.push_back(aom);
}
-// Part of the attachment structure, not used yet!
void PlayerSAO::setAttachment(ServerActiveObject *parent, std::string bone, v3f position, v3f rotation)
-{
- std::string str = gob_cmd_set_attachment(); // <- parameters here
+{
+ // 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.
+ // 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.
+
+ // Server attachment:
+ m_parent = parent;
+
+ // Client attachment:
+ std::string str = gob_cmd_set_attachment(parent->getId(), bone, position, rotation);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push_back(aom);