From 3c75377ce679094dfe55ee9aa872dabffd2ba3f0 Mon Sep 17 00:00:00 2001 From: DarkoGNU <42816979+DarkoGNU@users.noreply.github.com> Date: Tue, 26 Apr 2022 00:16:40 +0200 Subject: Implement relative SendPlayerMoveLook. Use it in TurnToDirt (#5413) * Implement relative SendPlayerMoveLook * Use relative teleport in cBlockFarmlandHandler::TurnToDirt * Static cast to UInt8. Explicit float values * Maybe explicit doubles, too * Fix TurnToDirt for some edge cases * Improve the height check in TurnToDirt * Const is good, right? * Const - the continuation --- src/Blocks/BlockFarmland.h | 24 +++++++++++++++--------- src/ClientHandle.cpp | 9 +++++++++ src/ClientHandle.h | 1 + src/Protocol/Protocol.h | 1 + src/Protocol/Protocol_1_8.cpp | 33 ++++++++++++++++++++++++++------- src/Protocol/Protocol_1_8.h | 1 + src/Protocol/Protocol_1_9.cpp | 36 ++++++++++++++++++++++++++++-------- src/Protocol/Protocol_1_9.h | 1 + 8 files changed, 82 insertions(+), 24 deletions(-) diff --git a/src/Blocks/BlockFarmland.h b/src/Blocks/BlockFarmland.h index 61ac872c8..3da27de43 100644 --- a/src/Blocks/BlockFarmland.h +++ b/src/Blocks/BlockFarmland.h @@ -44,7 +44,7 @@ public: /** Turns farmland into dirt. Will first check for any colliding entities and teleport them to a higher position. */ - static void TurnToDirt(cChunk & a_Chunk, Vector3i a_AbsPos, Vector3i a_RelPos) + static void TurnToDirt(cChunk & a_Chunk, const Vector3i a_AbsPos, const Vector3i a_RelPos) { static const auto FarmlandHeight = cBlockInfo::GetBlockHeight(E_BLOCK_FARMLAND); static const auto FullHeightDelta = 1 - FarmlandHeight; @@ -53,23 +53,29 @@ public: cBoundingBox(Vector3d(0.5, FarmlandHeight, 0.5) + a_AbsPos, 0.5, FullHeightDelta), [&](cEntity & Entity) { - if (!Entity.IsOnGround()) + const auto GroundHeight = a_AbsPos.y + 1; + + // A simple IsOnGround isn't enough. It will return true when + // e.g. a piston pushes a farmland block into an entity's head. + // Maybe it's also possible than an entity is falling, it's + // still not on the ground, but it's less than 0.0625 blocks + // higher than the farmland block + if ((Entity.GetPosY() < a_AbsPos.y + FarmlandHeight) || (Entity.GetPosY() >= GroundHeight)) { return false; } - Entity.AddPosY(FullHeightDelta); // Players need a packet that will update their position if (Entity.IsPlayer()) { - auto Player = static_cast(&Entity); - // This works, but it's much worse than Vanilla. - // This can be easily improved by implementing relative - // "Player Position And Look" packets! See - // https://wiki.vg/Protocol#Player_Position_And_Look_.28clientbound.29 - Player->GetClientHandle()->SendPlayerMoveLook(); + const auto HeightIncrease = GroundHeight - Entity.GetPosY(); + const auto Player = static_cast(&Entity); + + Player->GetClientHandle()->SendPlayerMoveLook(Vector3d(0.0, HeightIncrease, 0.0), 0.0f, 0.0f, true); } + Entity.SetPosY(GroundHeight); + return false; }); diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index db54cc77b..ef596baf0 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -2852,6 +2852,15 @@ void cClientHandle::SendPlayerListUpdatePing() +void cClientHandle::SendPlayerMoveLook (const Vector3d a_Pos, const float a_Yaw, const float a_Pitch, const bool a_IsRelative) +{ + m_Protocol->SendPlayerMoveLook(a_Pos, a_Yaw, a_Pitch, a_IsRelative); +} + + + + + void cClientHandle::SendPlayerMoveLook(void) { /* diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 66ae7f20e..9f3cbb18d 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -204,6 +204,7 @@ public: // tolua_export void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName); void SendPlayerListUpdateGameMode (const cPlayer & a_Player); void SendPlayerListUpdatePing (); + void SendPlayerMoveLook (Vector3d a_Pos, float a_Yaw, float a_Pitch, bool a_IsRelative); void SendPlayerMoveLook (void); void SendPlayerPermissionLevel (void); void SendPlayerPosition (void); diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 4f7590c2c..f1d85f014 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -422,6 +422,7 @@ public: virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) = 0; virtual void SendPlayerListUpdatePing () = 0; virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) = 0; + virtual void SendPlayerMoveLook (Vector3d a_Pos, float a_Yaw, float a_Pitch, bool a_IsRelative) = 0; virtual void SendPlayerMoveLook (void) = 0; virtual void SendPlayerPermissionLevel (void) = 0; virtual void SendPlayerPosition (void) = 0; diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index 7a3cd3b90..cbb13e68e 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -1136,18 +1136,37 @@ void cProtocol_1_8_0::SendPlayerListUpdatePing() -void cProtocol_1_8_0::SendPlayerMoveLook(void) +void cProtocol_1_8_0::SendPlayerMoveLook (const Vector3d a_Pos, const float a_Yaw, const float a_Pitch, const bool a_IsRelative) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktPlayerMoveLook); + Pkt.WriteBEDouble(a_Pos.x); + Pkt.WriteBEDouble(a_Pos.y); + Pkt.WriteBEDouble(a_Pos.z); + Pkt.WriteBEFloat(a_Yaw); + Pkt.WriteBEFloat(a_Pitch); + + if (a_IsRelative) + { + // Set all bits to 1 - makes everything relative + Pkt.WriteBEUInt8(static_cast(-1)); + } + else + { + // Set all bits to 0 - make everything absolute + Pkt.WriteBEUInt8(0); + } +} + + + + + +void cProtocol_1_8_0::SendPlayerMoveLook(void) +{ cPlayer * Player = m_Client->GetPlayer(); - Pkt.WriteBEDouble(Player->GetPosX()); - Pkt.WriteBEDouble(Player->GetPosY()); - Pkt.WriteBEDouble(Player->GetPosZ()); - Pkt.WriteBEFloat(static_cast(Player->GetYaw())); - Pkt.WriteBEFloat(static_cast(Player->GetPitch())); - Pkt.WriteBEUInt8(0); + SendPlayerMoveLook(Player->GetPosition(), static_cast(Player->GetYaw()), static_cast(Player->GetPitch()), false); } diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h index 59dacbca0..eaa8813be 100644 --- a/src/Protocol/Protocol_1_8.h +++ b/src/Protocol/Protocol_1_8.h @@ -93,6 +93,7 @@ public: virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) override; virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; virtual void SendPlayerListUpdatePing () override; + virtual void SendPlayerMoveLook (Vector3d a_Pos, float a_Yaw, float a_Pitch, bool a_IsRelative) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPermissionLevel (void) override; virtual void SendPlayerPosition (void) override; diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index 07ab4caf7..dd2133f77 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -466,18 +466,28 @@ void cProtocol_1_9_0::SendMapData(const cMap & a_Map, int a_DataStartX, int a_Da -void cProtocol_1_9_0::SendPlayerMoveLook(void) +void cProtocol_1_9_0::SendPlayerMoveLook (const Vector3d a_Pos, const float a_Yaw, const float a_Pitch, const bool a_IsRelative) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktPlayerMoveLook); - cPlayer * Player = m_Client->GetPlayer(); - Pkt.WriteBEDouble(Player->GetPosX()); - Pkt.WriteBEDouble(Player->GetPosY()); - Pkt.WriteBEDouble(Player->GetPosZ()); - Pkt.WriteBEFloat(static_cast(Player->GetYaw())); - Pkt.WriteBEFloat(static_cast(Player->GetPitch())); - Pkt.WriteBEUInt8(0); + Pkt.WriteBEDouble(a_Pos.x); + Pkt.WriteBEDouble(a_Pos.y); + Pkt.WriteBEDouble(a_Pos.z); + Pkt.WriteBEFloat(a_Yaw); + Pkt.WriteBEFloat(a_Pitch); + + if (a_IsRelative) + { + // Set all bits to 1 - makes everything relative + Pkt.WriteBEUInt8(static_cast(-1)); + } + else + { + // Set all bits to 0 - make everything absolute + Pkt.WriteBEUInt8(0); + } + Pkt.WriteVarInt32(++m_OutstandingTeleportId); // This teleport ID hasn't been confirmed yet @@ -488,6 +498,16 @@ void cProtocol_1_9_0::SendPlayerMoveLook(void) +void cProtocol_1_9_0::SendPlayerMoveLook(void) +{ + cPlayer * Player = m_Client->GetPlayer(); + SendPlayerMoveLook(Player->GetPosition(), static_cast(Player->GetYaw()), static_cast(Player->GetPitch()), false); +} + + + + + void cProtocol_1_9_0::SendPlayerPermissionLevel() { const cPlayer & Player = *m_Client->GetPlayer(); diff --git a/src/Protocol/Protocol_1_9.h b/src/Protocol/Protocol_1_9.h index 5f4bbed59..e56d7e2d2 100644 --- a/src/Protocol/Protocol_1_9.h +++ b/src/Protocol/Protocol_1_9.h @@ -51,6 +51,7 @@ public: virtual void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) override; virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; + virtual void SendPlayerMoveLook (Vector3d a_Pos, float a_Yaw, float a_Pitch, bool a_IsRelative) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPermissionLevel() override; virtual void SendPlayerSpawn (const cPlayer & a_Player) override; -- cgit v1.2.3