std::string PlayerSAO::getClientInitializationData(u16 protocol_version) { std::ostringstream os(std::ios::binary); if(protocol_version >= 15) { writeU8(os, 1); // version os<<serializeString(m_player->getName()); // name writeU8(os, 1); // is_player writeS16(os, getId()); //id writeV3F1000(os, m_base_position + v3f(0,BS*1,0)); writeF1000(os, m_yaw); writeS16(os, getHP()); std::ostringstream msg_os(std::ios::binary); msg_os << serializeLongString(getPropertyPacket()); // message 1 msg_os << serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2 msg_os << serializeLongString(gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3 for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) { msg_os << serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size } msg_os << serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4 msg_os << serializeLongString(gob_cmd_update_physics_override(m_physics_override_speed, m_physics_override_jump, m_physics_override_gravity, m_physics_override_sneak, m_physics_override_sneak_glitch)); // 5 // (GENERIC_CMD_UPDATE_NAMETAG_ATTRIBUTES) : Deprecated, for backwards compatibility only. msg_os << serializeLongString(gob_cmd_update_nametag_attributes(m_prop.nametag_color)); // 6 int message_count = 6 + m_bone_position.size(); for (UNORDERED_SET<int>::const_iterator ii = m_attachment_child_ids.begin(); ii != m_attachment_child_ids.end(); ++ii) { if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) { message_count++; msg_os << serializeLongString(gob_cmd_update_infant(*ii, obj->getSendType(), obj->getClientInitializationData(protocol_version))); } } writeU8(os, message_count); os.write(msg_os.str().c_str(), msg_os.str().size()); } else { writeU8(os, 0); // version os<<serializeString(m_player->getName()); // name writeU8(os, 1); // is_player writeV3F1000(os, m_base_position + v3f(0,BS*1,0)); writeF1000(os, m_yaw); writeS16(os, getHP()); writeU8(os, 2); // number of messages stuffed in here os<<serializeLongString(getPropertyPacket()); // message 1 os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2 } // return result return os.str(); }
std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) { std::ostringstream os(std::ios::binary); if(protocol_version >= 14) { writeU8(os, 1); // version os<<serializeString(""); // name writeU8(os, 0); // is_player writeS16(os, getId()); //id writeV3F1000(os, m_base_position); writeF1000(os, m_yaw); writeS16(os, m_hp); std::ostringstream msg_os(std::ios::binary); msg_os << serializeLongString(getPropertyPacket()); // message 1 msg_os << serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2 msg_os << serializeLongString(gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3 for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) { msg_os << serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size } msg_os << serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4 int message_count = 4 + m_bone_position.size(); for (UNORDERED_SET<int>::const_iterator ii = m_attachment_child_ids.begin(); (ii != m_attachment_child_ids.end()); ++ii) { if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) { message_count++; msg_os << serializeLongString(gob_cmd_update_infant(*ii, obj->getSendType(), obj->getClientInitializationData(protocol_version))); } } writeU8(os, message_count); os.write(msg_os.str().c_str(), msg_os.str().size()); } else { writeU8(os, 0); // version os<<serializeString(""); // name writeU8(os, 0); // is_player writeV3F1000(os, m_base_position); writeF1000(os, m_yaw); writeS16(os, m_hp); writeU8(os, 2); // number of messages stuffed in here os<<serializeLongString(getPropertyPacket()); // message 1 os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2 } // return result return os.str(); }
std::string PlayerSAO::getClientInitializationData(u16 protocol_version) { std::ostringstream os(std::ios::binary); if(protocol_version >= 15) { writeU8(os, 1); // version os<<serializeString(m_player->getName()); // name writeU8(os, 1); // is_player writeS16(os, getId()); //id writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0)); writeF1000(os, m_player->getYaw()); writeS16(os, getHP()); writeU8(os, 6 + m_bone_position.size()); // number of messages stuffed in here os<<serializeLongString(getPropertyPacket()); // message 1 os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2 os<<serializeLongString(gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3 for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size } os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4 os<<serializeLongString(gob_cmd_update_physics_override(m_physics_override_speed, m_physics_override_jump, m_physics_override_gravity, m_physics_override_sneak, m_physics_override_sneak_glitch)); // 5 os << serializeLongString(gob_cmd_update_nametag_attributes(m_nametag_color)); // 6 } else { writeU8(os, 0); // version os<<serializeString(m_player->getName()); // name writeU8(os, 1); // is_player writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0)); writeF1000(os, m_player->getYaw()); writeS16(os, getHP()); writeU8(os, 2); // number of messages stuffed in here os<<serializeLongString(getPropertyPacket()); // message 1 os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2 } // return result return os.str(); }
std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) { std::ostringstream os(std::ios::binary); if(protocol_version >= 14) { writeU8(os, 1); // version os<<serializeString(""); // name writeU8(os, 0); // is_player writeS16(os, getId()); //id writeV3F1000(os, m_base_position); writeF1000(os, m_yaw); writeS16(os, m_hp); writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here os<<serializeLongString(getPropertyPacket()); // message 1 os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2 os<<serializeLongString(gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3 for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size } os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4 } else { writeU8(os, 0); // version os<<serializeString(""); // name writeU8(os, 0); // is_player writeV3F1000(os, m_base_position); writeF1000(os, m_yaw); writeS16(os, m_hp); writeU8(os, 2); // number of messages stuffed in here os<<serializeLongString(getPropertyPacket()); // message 1 os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2 } // return result return os.str(); }
void PlayerSAO::step(float dtime, bool send_recommended) { if(!m_properties_sent) { m_properties_sent = true; std::string str = getPropertyPacket(); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(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); ((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id); } //dstream<<"PlayerSAO::step: dtime: "<<dtime<<std::endl; // Set lag pool maximums based on estimated lag const float LAG_POOL_MIN = 5.0; float lag_pool_max = m_env->getMaxLagEstimate() * 2.0; if(lag_pool_max < LAG_POOL_MIN) lag_pool_max = LAG_POOL_MIN; m_dig_pool.setMax(lag_pool_max); m_move_pool.setMax(lag_pool_max); // Increment cheat prevention timers m_dig_pool.add(dtime); m_move_pool.add(dtime); 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(isAttached()) { v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition(); m_last_good_position = pos; m_player->setPosition(pos); } if(send_recommended == false) return; // If the object is attached client-side, don't waste bandwidth sending its position to clients if(m_position_not_sent && !isAttached()) { m_position_not_sent = false; float update_interval = m_env->getSendRecommendedInterval(); v3f pos; 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( pos, v3f(0,0,0), v3f(0,0,0), m_player->getYaw(), true, false, update_interval ); // create message and add to list ActiveObjectMessage aom(getId(), false, str); m_messages_out.push(aom); } if(m_armor_groups_sent == false) { m_armor_groups_sent = true; std::string str = gob_cmd_update_armor_groups( m_armor_groups); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if(m_physics_override_sent == false){ m_physics_override_sent = true; std::string str = gob_cmd_update_physics_override(m_physics_override_speed, m_physics_override_jump, m_physics_override_gravity, m_physics_override_sneak, m_physics_override_sneak_glitch); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if(m_animation_sent == false){ m_animation_sent = true; std::string str = gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if(m_bone_position_sent == false){ m_bone_position_sent = true; for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } } if(m_attachment_sent == false){ m_attachment_sent = true; std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if (m_nametag_sent == false) { m_nametag_sent = true; std::string str = gob_cmd_update_nametag_attributes(m_nametag_color); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } }
void LuaEntitySAO::step(float dtime, bool send_recommended) { if(!m_properties_sent) { m_properties_sent = true; std::string str = getPropertyPacket(); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(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(isAttached()) { 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); } 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 v3f p_pos = m_base_position; v3f p_velocity = m_velocity; v3f p_acceleration = m_acceleration; moveresult = collisionMoveSimple(m_env,m_env->getGameDef(), pos_max_d, box, m_prop.stepheight, dtime, p_pos, p_velocity, p_acceleration, this, m_prop.collideWithObjects); // 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_prop.automatic_face_movement_dir) && (fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)){ m_yaw = atan2(m_velocity.Z,m_velocity.X) * 180 / M_PI + m_prop.automatic_face_movement_dir_offset; } } if(m_registered){ m_env->getScriptIface()->luaentity_Step(m_id, dtime); } if(send_recommended == false) return; if(!isAttached()) { // 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){ m_armor_groups_sent = true; std::string str = gob_cmd_update_armor_groups( m_armor_groups); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if(m_animation_sent == false){ m_animation_sent = true; std::string str = gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if(m_bone_position_sent == false){ m_bone_position_sent = true; for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } } if(m_attachment_sent == false){ m_attachment_sent = true; std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } }
void PlayerSAO::step(float dtime, bool send_recommended) { if(!m_properties_sent) { m_properties_sent = true; std::string str = getPropertyPacket(); // create message and add to list ActiveObjectMessage aom(getId(), true, str); 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(isAttached()) { 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); } else { if(m_is_singleplayer || g_settings->getBool("disable_anticheat")) { m_last_good_position = m_player->getPosition(); m_last_good_position_age = 0; } 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 { // 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_moved = true; } m_last_good_position_age = 0; } } } if(send_recommended == false) return; // If the object is attached client-side, don't waste bandwidth sending its position to clients if(m_position_not_sent && !isAttached()) { m_position_not_sent = false; float update_interval = m_env->getSendRecommendedInterval(); v3f pos; 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( pos, v3f(0,0,0), v3f(0,0,0), m_player->getYaw(), true, false, update_interval ); // create message and add to list ActiveObjectMessage aom(getId(), false, str); m_messages_out.push_back(aom); } if(m_wielded_item_not_sent) { m_wielded_item_not_sent = false; // GenericCAO has no special way to show this } if(m_armor_groups_sent == false){ m_armor_groups_sent = true; std::string str = gob_cmd_update_armor_groups( m_armor_groups); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push_back(aom); } if(m_animation_sent == false){ m_animation_sent = true; std::string str = gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push_back(aom); } if(m_bone_position_sent == false){ m_bone_position_sent = true; for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push_back(aom); } } if(m_attachment_sent == false){ m_attachment_sent = true; std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push_back(aom); } }
void PlayerSAO::step(float dtime, bool send_recommended) { if (m_drowning_interval.step(dtime, 2.0)) { // get head position v3s16 p = floatToInt(m_base_position + v3f(0, BS * 1.6, 0), BS); MapNode n = m_env->getMap().getNodeNoEx(p); const ContentFeatures &c = m_env->getGameDef()->ndef()->get(n); // If node generates drown if (c.drowning > 0 && m_hp > 0) { if (m_breath > 0) setBreath(m_breath - 1); // No more breath, damage player if (m_breath == 0) { setHP(m_hp - c.drowning); m_env->getGameDef()->SendPlayerHPOrDie(this); } } } if (m_breathing_interval.step(dtime, 0.5)) { // get head position v3s16 p = floatToInt(m_base_position + v3f(0, BS * 1.6, 0), BS); MapNode n = m_env->getMap().getNodeNoEx(p); const ContentFeatures &c = m_env->getGameDef()->ndef()->get(n); // If player is alive & no drowning, breath if (m_hp > 0 && m_breath < PLAYER_MAX_BREATH && c.drowning == 0) setBreath(m_breath + 1); } if (m_node_hurt_interval.step(dtime, 1.0)) { // Feet, middle and head v3s16 p1 = floatToInt(m_base_position + v3f(0, BS*0.1, 0), BS); MapNode n1 = m_env->getMap().getNodeNoEx(p1); v3s16 p2 = floatToInt(m_base_position + v3f(0, BS*0.8, 0), BS); MapNode n2 = m_env->getMap().getNodeNoEx(p2); v3s16 p3 = floatToInt(m_base_position + v3f(0, BS*1.6, 0), BS); MapNode n3 = m_env->getMap().getNodeNoEx(p3); u32 damage_per_second = 0; damage_per_second = MYMAX(damage_per_second, m_env->getGameDef()->ndef()->get(n1).damage_per_second); damage_per_second = MYMAX(damage_per_second, m_env->getGameDef()->ndef()->get(n2).damage_per_second); damage_per_second = MYMAX(damage_per_second, m_env->getGameDef()->ndef()->get(n3).damage_per_second); if (damage_per_second != 0 && m_hp > 0) { s16 newhp = ((s32) damage_per_second > m_hp ? 0 : m_hp - damage_per_second); setHP(newhp); m_env->getGameDef()->SendPlayerHPOrDie(this); } } if (!m_properties_sent) { m_properties_sent = true; std::string str = getPropertyPacket(); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(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); setBasePosition(m_last_good_position); m_env->getGameDef()->SendMovePlayer(m_peer_id); } //dstream<<"PlayerSAO::step: dtime: "<<dtime<<std::endl; // Set lag pool maximums based on estimated lag const float LAG_POOL_MIN = 5.0; float lag_pool_max = m_env->getMaxLagEstimate() * 2.0; if(lag_pool_max < LAG_POOL_MIN) lag_pool_max = LAG_POOL_MIN; m_dig_pool.setMax(lag_pool_max); m_move_pool.setMax(lag_pool_max); // Increment cheat prevention timers m_dig_pool.add(dtime); m_move_pool.add(dtime); m_time_from_last_teleport += dtime; 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 (isAttached()) { v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition(); m_last_good_position = pos; setBasePosition(pos); } if (!send_recommended) return; // If the object is attached client-side, don't waste bandwidth sending its position to clients if(m_position_not_sent && !isAttached()) { m_position_not_sent = false; float update_interval = m_env->getSendRecommendedInterval(); v3f pos; if(isAttached()) // Just in case we ever do send attachment position too pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition(); else pos = m_base_position + v3f(0,BS*1,0); std::string str = gob_cmd_update_position( pos, v3f(0,0,0), v3f(0,0,0), m_yaw, true, false, update_interval ); // create message and add to list ActiveObjectMessage aom(getId(), false, str); m_messages_out.push(aom); } if (!m_armor_groups_sent) { m_armor_groups_sent = true; std::string str = gob_cmd_update_armor_groups( m_armor_groups); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if (!m_physics_override_sent) { m_physics_override_sent = true; std::string str = gob_cmd_update_physics_override(m_physics_override_speed, m_physics_override_jump, m_physics_override_gravity, m_physics_override_sneak, m_physics_override_sneak_glitch, m_physics_override_new_move); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if (!m_animation_sent) { m_animation_sent = true; std::string str = gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if (!m_bone_position_sent) { m_bone_position_sent = true; for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) { std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } } if (!m_attachment_sent){ m_attachment_sent = true; std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } }
void PlayerSAO::step(float dtime, bool send_recommended) { if (m_drowning_interval.step(dtime, 2.0f)) { // Get nose/mouth position, approximate with eye position v3s16 p = floatToInt(getEyePosition(), BS); MapNode n = m_env->getMap().getNodeNoEx(p); const ContentFeatures &c = m_env->getGameDef()->ndef()->get(n); // If node generates drown if (c.drowning > 0 && m_hp > 0) { if (m_breath > 0) setBreath(m_breath - 1); // No more breath, damage player if (m_breath == 0) { PlayerHPChangeReason reason(PlayerHPChangeReason::DROWNING); setHP(m_hp - c.drowning, reason); m_env->getGameDef()->SendPlayerHPOrDie(this, reason); } } } if (m_breathing_interval.step(dtime, 0.5f)) { // Get nose/mouth position, approximate with eye position v3s16 p = floatToInt(getEyePosition(), BS); MapNode n = m_env->getMap().getNodeNoEx(p); const ContentFeatures &c = m_env->getGameDef()->ndef()->get(n); // If player is alive & no drowning, breathe if (m_hp > 0 && m_breath < m_prop.breath_max && c.drowning == 0) setBreath(m_breath + 1); } if (m_node_hurt_interval.step(dtime, 1.0f)) { u32 damage_per_second = 0; // Lowest and highest damage points are 0.1 within collisionbox float dam_top = m_prop.collisionbox.MaxEdge.Y - 0.1f; // Sequence of damage points, starting 0.1 above feet and progressing // upwards in 1 node intervals, stopping below top damage point. for (float dam_height = 0.1f; dam_height < dam_top; dam_height++) { v3s16 p = floatToInt(m_base_position + v3f(0.0f, dam_height * BS, 0.0f), BS); MapNode n = m_env->getMap().getNodeNoEx(p); damage_per_second = std::max(damage_per_second, m_env->getGameDef()->ndef()->get(n).damage_per_second); } // Top damage point v3s16 ptop = floatToInt(m_base_position + v3f(0.0f, dam_top * BS, 0.0f), BS); MapNode ntop = m_env->getMap().getNodeNoEx(ptop); damage_per_second = std::max(damage_per_second, m_env->getGameDef()->ndef()->get(ntop).damage_per_second); if (damage_per_second != 0 && m_hp > 0) { s16 newhp = ((s32) damage_per_second > m_hp ? 0 : m_hp - damage_per_second); PlayerHPChangeReason reason(PlayerHPChangeReason::NODE_DAMAGE); setHP(newhp, reason); m_env->getGameDef()->SendPlayerHPOrDie(this, reason); } } if (!m_properties_sent) { m_properties_sent = true; std::string str = getPropertyPacket(); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(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.0f, 0.0f, 0.0f); m_attachment_rotation = v3f(0.0f, 0.0f, 0.0f); setBasePosition(m_last_good_position); m_env->getGameDef()->SendMovePlayer(m_peer_id); } //dstream<<"PlayerSAO::step: dtime: "<<dtime<<std::endl; // Set lag pool maximums based on estimated lag const float LAG_POOL_MIN = 5.0f; float lag_pool_max = m_env->getMaxLagEstimate() * 2.0f; if(lag_pool_max < LAG_POOL_MIN) lag_pool_max = LAG_POOL_MIN; m_dig_pool.setMax(lag_pool_max); m_move_pool.setMax(lag_pool_max); // Increment cheat prevention timers m_dig_pool.add(dtime); m_move_pool.add(dtime); m_time_from_last_teleport += dtime; 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 (isAttached()) { v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition(); m_last_good_position = pos; setBasePosition(pos); } if (!send_recommended) return; // If the object is attached client-side, don't waste bandwidth sending its // position to clients. if (m_position_not_sent && !isAttached()) { m_position_not_sent = false; float update_interval = m_env->getSendRecommendedInterval(); v3f pos; if (isAttached()) // Just in case we ever do send attachment position too pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition(); else pos = m_base_position; std::string str = gob_cmd_update_position( pos, v3f(0.0f, 0.0f, 0.0f), v3f(0.0f, 0.0f, 0.0f), m_yaw, true, false, update_interval ); // create message and add to list ActiveObjectMessage aom(getId(), false, str); m_messages_out.push(aom); } if (!m_armor_groups_sent) { m_armor_groups_sent = true; std::string str = gob_cmd_update_armor_groups( m_armor_groups); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if (!m_physics_override_sent) { m_physics_override_sent = true; std::string str = gob_cmd_update_physics_override(m_physics_override_speed, m_physics_override_jump, m_physics_override_gravity, m_physics_override_sneak, m_physics_override_sneak_glitch, m_physics_override_new_move); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if (!m_animation_sent) { m_animation_sent = true; std::string str = gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if (!m_bone_position_sent) { m_bone_position_sent = true; for (std::unordered_map<std::string, core::vector2d<v3f>>::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) { std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } } if (!m_attachment_sent) { m_attachment_sent = true; std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } }