]> git.lizzy.rs Git - minetest.git/blobdiff - src/content_sao.cpp
Fix pathfinder bugs: returning nil frequently, broken A*, jump through solid nodes...
[minetest.git] / src / content_sao.cpp
index 0f1e2f435c623f3d29362be128f48038d28765ab..5119223a7c43493addcdfd1b02c74eaf27f4362b 100644 (file)
@@ -624,7 +624,7 @@ void LuaEntitySAO::getStaticData(std::string *result) const
        *result = os.str();
 }
 
-int LuaEntitySAO::punch(v3f dir,
+u16 LuaEntitySAO::punch(v3f dir,
                const ToolCapabilities *toolcap,
                ServerActiveObject *puncher,
                float time_from_last_punch)
@@ -638,12 +638,13 @@ int LuaEntitySAO::punch(v3f dir,
        FATAL_ERROR_IF(!puncher, "Punch action called without SAO");
 
        s32 old_hp = getHP();
-       const ItemStack &punchitem = puncher->getWieldedItem();
+       ItemStack selected_item, hand_item;
+       ItemStack tool_item = puncher->getWieldedItem(&selected_item, &hand_item);
 
        PunchDamageResult result = getPunchDamage(
                        m_armor_groups,
                        toolcap,
-                       &punchitem,
+                       &tool_item,
                        time_from_last_punch);
 
        bool damage_handled = m_env->getScriptIface()->luaentity_Punch(m_id, puncher,
@@ -863,12 +864,11 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t p
        m_peer_id(peer_id_),
        m_is_singleplayer(is_singleplayer)
 {
-       assert(m_peer_id != 0); // pre-condition
+       SANITY_CHECK(m_peer_id != PEER_ID_INEXISTENT);
 
        m_prop.hp_max = PLAYER_MAX_HP_DEFAULT;
        m_prop.breath_max = PLAYER_MAX_BREATH_DEFAULT;
        m_prop.physical = false;
-       m_prop.weight = 75;
        m_prop.collisionbox = aabb3f(-0.3f, 0.0f, -0.3f, 0.3f, 1.77f, 0.3f);
        m_prop.selectionbox = aabb3f(-0.3f, 0.0f, -0.3f, 0.3f, 1.77f, 0.3f);
        m_prop.pointable = true;
@@ -984,7 +984,7 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
 
 void PlayerSAO::getStaticData(std::string * result) const
 {
-       FATAL_ERROR("Deprecated function");
+       FATAL_ERROR("Obsolete function");
 }
 
 void PlayerSAO::step(float dtime, bool send_recommended)
@@ -992,7 +992,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
        if (!isImmortal() && 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);
+               MapNode n = m_env->getMap().getNode(p);
                const ContentFeatures &c = m_env->getGameDef()->ndef()->get(n);
                // If node generates drown
                if (c.drowning > 0 && m_hp > 0) {
@@ -1011,7 +1011,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
        if (m_breathing_interval.step(dtime, 0.5f) && !isImmortal()) {
                // Get nose/mouth position, approximate with eye position
                v3s16 p = floatToInt(getEyePosition(), BS);
-               MapNode n = m_env->getMap().getNodeNoEx(p);
+               MapNode n = m_env->getMap().getNode(p);
                const ContentFeatures &c = m_env->getGameDef()->ndef()->get(n);
                // If player is alive & not drowning & not in ignore & not immortal, breathe
                if (m_breath < m_prop.breath_max && c.drowning == 0 &&
@@ -1030,7 +1030,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
                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);
+                       MapNode n = m_env->getMap().getNode(p);
                        const ContentFeatures &c = m_env->getGameDef()->ndef()->get(n);
                        if (c.damage_per_second > damage_per_second) {
                                damage_per_second = c.damage_per_second;
@@ -1041,7 +1041,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
                // 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);
+               MapNode ntop = m_env->getMap().getNode(ptop);
                const ContentFeatures &c = m_env->getGameDef()->ndef()->get(ntop);
                if (c.damage_per_second > damage_per_second) {
                        damage_per_second = c.damage_per_second;
@@ -1091,6 +1091,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
        m_time_from_last_teleport += dtime;
        m_time_from_last_punch += dtime;
        m_nocheat_dig_time += dtime;
+       m_max_speed_override_time = MYMAX(m_max_speed_override_time - dtime, 0.0f);
 
        // Each frame, parent position is copied if the object is attached,
        // otherwise it's calculated normally.
@@ -1105,14 +1106,14 @@ void PlayerSAO::step(float dtime, bool send_recommended)
        if (!send_recommended)
                return;
 
-       // If the object is attached client-side, don't waste bandwidth sending its
-       // position or rotation to clients.
-       if (m_position_not_sent && !isAttached()) {
+       if (m_position_not_sent) {
                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();
+               // When attached, the position is only sent to clients where the
+               // parent isn't known
+               if (isAttached())
+                       pos = m_last_good_position;
                else
                        pos = m_base_position;
 
@@ -1271,7 +1272,7 @@ void PlayerSAO::setLookPitchAndSend(const float pitch)
        m_env->getGameDef()->SendMovePlayer(m_peer_id);
 }
 
-int PlayerSAO::punch(v3f dir,
+u16 PlayerSAO::punch(v3f dir,
        const ToolCapabilities *toolcap,
        ServerActiveObject *puncher,
        float time_from_last_punch)
@@ -1375,10 +1376,9 @@ u16 PlayerSAO::getWieldIndex() const
        return m_player->getWieldIndex();
 }
 
-ItemStack PlayerSAO::getWieldedItem() const
+ItemStack PlayerSAO::getWieldedItem(ItemStack *selected, ItemStack *hand) const
 {
-       ItemStack selected_item, hand_item;
-       return m_player->getWieldedItem(&selected_item, &hand_item);
+       return m_player->getWieldedItem(selected, hand);
 }
 
 bool PlayerSAO::setWieldedItem(const ItemStack &item)
@@ -1393,7 +1393,7 @@ bool PlayerSAO::setWieldedItem(const ItemStack &item)
 
 void PlayerSAO::disconnected()
 {
-       m_peer_id = 0;
+       m_peer_id = PEER_ID_INEXISTENT;
        m_pending_removal = true;
 }
 
@@ -1412,6 +1412,19 @@ std::string PlayerSAO::getPropertyPacket()
        return gob_cmd_set_properties(m_prop);
 }
 
+void PlayerSAO::setMaxSpeedOverride(const v3f &vel)
+{
+       if (m_max_speed_override_time == 0.0f)
+               m_max_speed_override = vel;
+       else
+               m_max_speed_override += vel;
+       if (m_player) {
+               float accel = MYMIN(m_player->movement_acceleration_default,
+                               m_player->movement_acceleration_air);
+               m_max_speed_override_time = m_max_speed_override.getLength() / accel / BS;
+       }
+}
+
 bool PlayerSAO::checkMovementCheat()
 {
        if (isAttached() || m_is_singleplayer ||
@@ -1431,6 +1444,14 @@ bool PlayerSAO::checkMovementCheat()
                too, and much more lightweight.
        */
 
+       float override_max_H, override_max_V;
+       if (m_max_speed_override_time > 0.0f) {
+               override_max_H = MYMAX(fabs(m_max_speed_override.X), fabs(m_max_speed_override.Z));
+               override_max_V = fabs(m_max_speed_override.Y);
+       } else {
+               override_max_H = override_max_V = 0.0f;
+       }
+
        float player_max_walk = 0; // horizontal movement
        float player_max_jump = 0; // vertical upwards movement
 
@@ -1439,10 +1460,13 @@ bool PlayerSAO::checkMovementCheat()
        else
                player_max_walk = m_player->movement_speed_walk; // Normal speed
        player_max_walk *= m_physics_override_speed;
+       player_max_walk = MYMAX(player_max_walk, override_max_H);
+
        player_max_jump = m_player->movement_speed_jump * m_physics_override_jump;
        // FIXME: Bouncy nodes cause practically unbound increase in Y speed,
        //        until this can be verified correctly, tolerate higher jumping speeds
        player_max_jump *= 2.0;
+       player_max_jump = MYMAX(player_max_jump, override_max_V);
 
        // Don't divide by zero!
        if (player_max_walk < 0.0001f)