From a7b029654c524d2da85d6ab9de2e4f1ae0bcc748 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 30 Sep 2020 18:54:36 +0100 Subject: Fix boats in the new physics system --- src/Entities/Boat.cpp | 138 +++++++++++++++++++++-------------------- src/Entities/Boat.h | 26 +++----- src/Protocol/Protocol_1_10.cpp | 6 +- src/Protocol/Protocol_1_11.cpp | 6 +- src/Protocol/Protocol_1_12.cpp | 6 +- src/Protocol/Protocol_1_13.cpp | 9 +-- src/Protocol/Protocol_1_8.cpp | 4 +- src/Protocol/Protocol_1_9.cpp | 6 +- 8 files changed, 97 insertions(+), 104 deletions(-) diff --git a/src/Entities/Boat.cpp b/src/Entities/Boat.cpp index aecbd8125..66ae8a894 100644 --- a/src/Entities/Boat.cpp +++ b/src/Entities/Boat.cpp @@ -15,10 +15,11 @@ cBoat::cBoat(Vector3d a_Pos, eMaterial a_Material) : - Super(etBoat, a_Pos, 1.5, 0.6), - m_LastDamage(0), m_ForwardDirection(0), - m_DamageTaken(0.0f), m_Material(a_Material), - m_RightPaddleUsed(false), m_LeftPaddleUsed(false) + Super(etBoat, a_Pos, 1.375, 0.5625), + m_Material(a_Material), + m_LeftPaddleUsed(false), + m_RightPaddleUsed(false), + m_ShouldShakeForwards(true) { SetMass(20.0f); SetGravity(-16.0f); @@ -41,53 +42,29 @@ void cBoat::SpawnOn(cClientHandle & a_ClientHandle) -void cBoat::BroadcastMovementUpdate(const cClientHandle * a_Exclude) +bool cBoat::DoTakeDamage(TakeDamageInfo & TDI) { - // Cannot use super::BroadcastMovementUpdate here, broadcasting position when not - // expected by the client breaks things. See https://github.com/cuberite/cuberite/pull/4488 + if ( + const auto Attacker = TDI.Attacker; - // Process packet sending every two ticks - if (GetWorld()->GetWorldAge() % 2 != 0) + (Attacker != nullptr) && + Attacker->IsPlayer() && + static_cast(Attacker)->IsGameModeCreative() + ) { - return; + TDI.FinalDamage = GetMaxHealth(); // Instant hit for creative + return Super::DoTakeDamage(TDI); } - Vector3i Diff = (GetPosition() * 32.0).Floor() - (m_LastSentPosition * 32.0).Floor(); - if (Diff.HasNonZeroLength()) // Have we moved? - { - m_World->BroadcastEntityPosition(*this, a_Exclude); - m_LastSentPosition = GetPosition(); - m_bDirtyOrientation = false; - } -} - - - - - -bool cBoat::DoTakeDamage(TakeDamageInfo & TDI) -{ - m_LastDamage = 10; if (!Super::DoTakeDamage(TDI)) { return false; } - m_World->BroadcastEntityMetadata(*this); + m_World->BroadcastEntityMetadata(*this); // Tell the client to play the shaking animation + m_ShouldShakeForwards = !m_ShouldShakeForwards; // The next shake goes the opposite direction - if (GetHealth() <= 0) - { - if (TDI.Attacker != nullptr) - { - if (TDI.Attacker->IsPlayer()) - { - cItems Pickups; - Pickups.Add(MaterialToItem(m_Material)); - m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 0, 0, 0, true); - } - } - Destroy(); - } + SetInvulnerableTicks(2); // Make rapid attacks have more of an effect return true; } @@ -101,7 +78,7 @@ void cBoat::OnRightClicked(cPlayer & a_Player) if (m_Attachee != nullptr) { - if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) + if (m_Attachee == &a_Player) { // This player is already sitting in, they want out. a_Player.Detach(); @@ -126,38 +103,61 @@ void cBoat::OnRightClicked(cPlayer & a_Player) -void cBoat::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) +void cBoat::GetDrops(cItems & a_Drops, cEntity * a_Killer) { - Super::Tick(a_Dt, a_Chunk); - if (!IsTicking()) + if ( + (a_Killer != nullptr) && + a_Killer->IsPlayer() && + !static_cast(a_Killer)->IsGameModeCreative() // No drops for creative + ) { - // The base class tick destroyed us - return; + a_Drops.Add(MaterialToItem(m_Material)); } - BroadcastMovementUpdate(); +} - SetSpeed(GetSpeed() * 0.97); // Slowly decrease the speed - if ((POSY_TOINT < 0) || (POSY_TOINT >= cChunkDef::Height)) - { - return; - } + + + +void cBoat::KilledBy(TakeDamageInfo & a_TDI) +{ + Super::KilledBy(a_TDI); + Destroy(); +} + + + + + +void cBoat::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) +{ + const auto Position = POS_TOINT; + const auto InWater = IsBlockWater(m_World->GetBlock(Position)); + const auto DtSec = std::chrono::duration_cast>(a_Dt).count(); // A real boat floats. // Propel to top water block and sit slightly beneath the waterline: - if (IsBlockWater(m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT)) && ((GetPosY() - POSY_TOINT) < 0.6)) + if (InWater) { - if (GetSpeedY() < 2) - { - const auto DtSec = std::chrono::duration_cast>(a_Dt).count(); - SetSpeedY((-m_Gravity + 1) * DtSec); - } + // Counteract gravity and provide a small upwards force: + SetSpeedY((-m_Gravity + 1) * DtSec); } - if (GetLastDamage() > 0) + auto Speed = GetSpeed(); + ApplyFriction(Speed, 0.9, DtSec); // Slowly decrease the speed + SetSpeed(Speed); + + Super::HandlePhysics(a_Dt, a_Chunk); + + const auto AbovePosition = Position.addedY(1); + const auto OnSurface = !IsBlockWater(m_World->GetBlock(AbovePosition)); + if (InWater && OnSurface) { - SetLastDamage(GetLastDamage() - 1); + SetSpeedY(0); + SetPosY(Position.y + 0.52); } + + BroadcastMovementUpdate(); } @@ -181,12 +181,18 @@ void cBoat::HandleSpeedFromAttachee(float a_Forward, float a_Sideways) -void cBoat::SetLastDamage(int TimeSinceLastHit) +float cBoat::GetDamageTaken(void) const { - m_LastDamage = TimeSinceLastHit; + return GetMaxHealth() - GetHealth(); +} + + + - // Tell the client to play the shaking animation - m_World->BroadcastEntityMetadata(*this); + +bool cBoat::ShouldShakeForwards(void) const +{ + return m_ShouldShakeForwards; } @@ -300,7 +306,3 @@ cItem cBoat::MaterialToItem(eMaterial a_Material) } UNREACHABLE("Unsupported boat material"); } - - - - diff --git a/src/Entities/Boat.h b/src/Entities/Boat.h index 4a583a26c..244d681a8 100644 --- a/src/Entities/Boat.h +++ b/src/Entities/Boat.h @@ -43,17 +43,13 @@ public: // cEntity overrides: virtual void SpawnOn(cClientHandle & a_ClientHandle) override; - virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = nullptr) override; virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer) override; + virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual bool DoTakeDamage(TakeDamageInfo & TDI) override; - virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; + virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override; - int GetLastDamage(void) const { return m_LastDamage; } - int GetForwardDirection(void) const { return m_ForwardDirection; } - - float GetDamageTaken(void) const { return m_DamageTaken; } - // tolua_begin /** Returns the eMaterial of the boat */ @@ -76,20 +72,18 @@ public: // tolua_end - bool IsRightPaddleUsed(void) const { return m_RightPaddleUsed; } bool IsLeftPaddleUsed(void) const { return m_LeftPaddleUsed; } + bool IsRightPaddleUsed(void) const { return m_RightPaddleUsed; } - void SetLastDamage(int TimeSinceLastHit); + float GetDamageTaken(void) const; + bool ShouldShakeForwards(void) const; - void UpdatePaddles(bool rightPaddleUsed, bool leftPaddleUsed); -private: - int m_LastDamage; - int m_ForwardDirection; + void UpdatePaddles(bool a_RightPaddleUsed, bool a_LeftPaddleUsed); - float m_DamageTaken; +private: eMaterial m_Material; - - bool m_RightPaddleUsed; bool m_LeftPaddleUsed; + bool m_RightPaddleUsed; + bool m_ShouldShakeForwards; } ; // tolua_export diff --git a/src/Protocol/Protocol_1_10.cpp b/src/Protocol/Protocol_1_10.cpp index f40bf7b73..9dc4a06f6 100644 --- a/src/Protocol/Protocol_1_10.cpp +++ b/src/Protocol/Protocol_1_10.cpp @@ -502,15 +502,15 @@ void cProtocol_1_10_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Pkt.WriteBEInt8(BOAT_LAST_HIT_TIME); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); + a_Pkt.WriteVarInt32(8); a_Pkt.WriteBEInt8(BOAT_FORWARD_DIRECTION); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); + a_Pkt.WriteVarInt32(Boat.ShouldShakeForwards() ? 1 : -1); a_Pkt.WriteBEInt8(BOAT_DAMAGE_TAKEN); a_Pkt.WriteBEInt8(METADATA_TYPE_FLOAT); - a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); + a_Pkt.WriteBEFloat(10 * Boat.GetDamageTaken()); a_Pkt.WriteBEInt8(BOAT_TYPE); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp index 1e07419ec..697e3c66b 100644 --- a/src/Protocol/Protocol_1_11.cpp +++ b/src/Protocol/Protocol_1_11.cpp @@ -768,15 +768,15 @@ void cProtocol_1_11_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Pkt.WriteBEInt8(BOAT_LAST_HIT_TIME); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); + a_Pkt.WriteVarInt32(8); a_Pkt.WriteBEInt8(BOAT_FORWARD_DIRECTION); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); + a_Pkt.WriteVarInt32(Boat.ShouldShakeForwards() ? 1 : -1); a_Pkt.WriteBEInt8(BOAT_DAMAGE_TAKEN); a_Pkt.WriteBEInt8(METADATA_TYPE_FLOAT); - a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); + a_Pkt.WriteBEFloat(10 * Boat.GetDamageTaken()); a_Pkt.WriteBEInt8(BOAT_TYPE); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); diff --git a/src/Protocol/Protocol_1_12.cpp b/src/Protocol/Protocol_1_12.cpp index 8a3076980..beefd587f 100644 --- a/src/Protocol/Protocol_1_12.cpp +++ b/src/Protocol/Protocol_1_12.cpp @@ -481,15 +481,15 @@ void cProtocol_1_12::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_ a_Pkt.WriteBEInt8(BOAT_LAST_HIT_TIME); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); + a_Pkt.WriteVarInt32(8); a_Pkt.WriteBEInt8(BOAT_FORWARD_DIRECTION); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); + a_Pkt.WriteVarInt32(Boat.ShouldShakeForwards() ? 1 : -1); a_Pkt.WriteBEInt8(BOAT_DAMAGE_TAKEN); a_Pkt.WriteBEInt8(METADATA_TYPE_FLOAT); - a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); + a_Pkt.WriteBEFloat(10 * Boat.GetDamageTaken()); a_Pkt.WriteBEInt8(BOAT_TYPE); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); diff --git a/src/Protocol/Protocol_1_13.cpp b/src/Protocol/Protocol_1_13.cpp index 0259565f5..342f8ad47 100644 --- a/src/Protocol/Protocol_1_13.cpp +++ b/src/Protocol/Protocol_1_13.cpp @@ -856,13 +856,13 @@ void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_ auto & Boat = static_cast(a_Entity); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatLastHitTime, EntityMetadataType::VarInt); - a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); + a_Pkt.WriteVarInt32(8); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatForwardDirection, EntityMetadataType::VarInt); - a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); + a_Pkt.WriteVarInt32(Boat.ShouldShakeForwards() ? 1 : -1); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatDamageTaken, EntityMetadataType::Float); - a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); + a_Pkt.WriteBEFloat(10 * Boat.GetDamageTaken()); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatType, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Boat.GetMaterial())); @@ -873,9 +873,6 @@ void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_ WriteEntityMetadata(a_Pkt, EntityMetadata::BoatLeftPaddleTurning, EntityMetadataType::Boolean); a_Pkt.WriteBool(static_cast(Boat.IsLeftPaddleUsed())); - WriteEntityMetadata(a_Pkt, EntityMetadata::BoatSplashTimer, EntityMetadataType::VarInt); - a_Pkt.WriteVarInt32(0); - break; } // case etBoat diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index c6b21fc3d..7d4a00078 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -2773,7 +2773,7 @@ void cProtocol_1_8_0::HandlePacketSteerVehicle(cByteBuffer & a_ByteBuffer) } else if ((Flags & 0x1) != 0) { - // jump + // TODO: Handle vehicle jump (for animals) } else { @@ -3915,7 +3915,7 @@ void cProtocol_1_8_0::WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & { if (!a_Entity.IsMob()) { - // No properties for anything else than mobs + // No properties for anything else other than mobs a_Pkt.WriteBEInt32(0); return; } diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index c170227b5..06f0b9012 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -1707,15 +1707,15 @@ void cProtocol_1_9_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a a_Pkt.WriteBEInt8(5); // Index 6: Time since last hit a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); + a_Pkt.WriteVarInt32(8); a_Pkt.WriteBEInt8(6); // Index 7: Forward direction a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); - a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); + a_Pkt.WriteVarInt32(Boat.ShouldShakeForwards() ? 1 : -1); a_Pkt.WriteBEInt8(7); // Index 8: Damage taken a_Pkt.WriteBEInt8(METADATA_TYPE_FLOAT); - a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); + a_Pkt.WriteBEFloat(10 * Boat.GetDamageTaken()); a_Pkt.WriteBEInt8(8); // Index 9: Type a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); -- cgit v1.2.3