From f5b599c9f45777f924f7980cadb2d3cc6431d8b8 Mon Sep 17 00:00:00 2001 From: TEDERIs Date: Tue, 18 Jun 2024 01:05:51 +0700 Subject: [PATCH] Ped sync improvements (PR #3480) --- Client/mods/deathmatch/logic/CClientPed.cpp | 21 ++-- Client/mods/deathmatch/logic/CPedSync.cpp | 96 +++++++++++---- Server/mods/deathmatch/logic/CPedSync.cpp | 6 +- .../logic/packets/CPedSyncPacket.cpp | 114 +++++++++++++----- .../deathmatch/logic/packets/CPedSyncPacket.h | 25 ++-- Shared/mods/deathmatch/logic/Utils.h | 9 ++ Shared/sdk/CVector.h | 12 +- Shared/sdk/net/bitstream.h | 4 + 8 files changed, 205 insertions(+), 82 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 1eaaa5c796..7fee88ce63 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -3325,7 +3325,7 @@ void CClientPed::SetTargetRotation(unsigned long ulDelay, float fRotation, float { m_ulBeginRotationTime = CClientTime::GetTime(); m_ulEndRotationTime = m_ulBeginRotationTime + ulDelay; - m_fBeginRotation = (m_pPlayerPed) ? m_pPlayerPed->GetTargetRotation() : m_fCurrentRotation; + m_fBeginRotation = (m_pPlayerPed) ? m_pPlayerPed->GetCurrentRotation() : m_fCurrentRotation; m_fTargetRotationA = fRotation; m_fBeginCameraRotation = GetCameraRotation(); m_fTargetCameraRotation = fCameraRotation; @@ -3383,23 +3383,24 @@ void CClientPed::Interpolate() { // We're not at the end? if (ulCurrentTime < m_ulEndRotationTime) - { - // Interpolate the player rotation - float fDeltaTime = float(m_ulEndRotationTime - m_ulBeginRotationTime); - float fDelta = GetOffsetDegrees(m_fBeginRotation, m_fTargetRotationA); - float fCameraDelta = GetOffsetDegrees(m_fBeginCameraRotation, m_fTargetCameraRotation); - float fProgress = float(ulCurrentTime - m_ulBeginRotationTime); - float fNewRotation = m_fBeginRotation + (fDelta / fDeltaTime * fProgress); - float fNewCameraRotation = m_fBeginCameraRotation + (fCameraDelta / fDeltaTime * fProgress); + { + const float fDelta = GetOffsetRadians(m_fBeginRotation, m_fTargetRotationA); // Hack for the wrap-around (the edge seems to be varying...) - if (fDelta < -5.0f || fDelta > 5.0f) + if (fDelta < -M_PI || fDelta > M_PI) { SetCurrentRotation(m_fTargetRotationA); SetCameraRotation(m_fTargetCameraRotation); } else { + // Interpolate the player rotation + const float fDeltaTime = float(m_ulEndRotationTime - m_ulBeginRotationTime); + const float fCameraDelta = GetOffsetRadians(m_fBeginCameraRotation, m_fTargetCameraRotation); + const float fProgress = float(ulCurrentTime - m_ulBeginRotationTime); + const float fNewRotation = m_fBeginRotation + fDelta * (fProgress / fDeltaTime); + const float fNewCameraRotation = m_fBeginCameraRotation + fCameraDelta * (fProgress / fDeltaTime); + SetCurrentRotation(fNewRotation); SetCameraRotation(fNewCameraRotation); } diff --git a/Client/mods/deathmatch/logic/CPedSync.cpp b/Client/mods/deathmatch/logic/CPedSync.cpp index d11e8f526f..8461ac1a87 100644 --- a/Client/mods/deathmatch/logic/CPedSync.cpp +++ b/Client/mods/deathmatch/logic/CPedSync.cpp @@ -179,29 +179,50 @@ void CPedSync::Packet_PedSync(NetBitStreamInterface& BitStream) unsigned char ucFlags = 0; BitStream.Read(ucFlags); - CVector vecPosition, vecMoveSpeed; + CVector vecPosition{ CVector::NoInit{} }, vecMoveSpeed{ CVector::NoInit{} }; float fRotation, fHealth, fArmor; bool bOnFire; bool bIsInWater; - // Read out the position - if (ucFlags & 0x01) + if (BitStream.Can(eBitStreamVersion::PedSync_Revision)) { - BitStream.Read(vecPosition.fX); - BitStream.Read(vecPosition.fY); - BitStream.Read(vecPosition.fZ); - } + // Read out the position + SPositionSync position(false); + if (ucFlags & 0x01) + BitStream.Read(&position); - // And rotation - if (ucFlags & 0x02) - BitStream.Read(fRotation); + // And rotation + SPedRotationSync rotation; + if (ucFlags & 0x02) + BitStream.Read(&rotation); + + // And the move speed + SVelocitySync velocity; + if (ucFlags & 0x04) + BitStream.Read(&velocity); - // And the move speed - if (ucFlags & 0x04) + vecPosition = position.data.vecPosition; + fRotation = rotation.data.fRotation; + vecMoveSpeed = velocity.data.vecVelocity; + } + else { - BitStream.Read(vecMoveSpeed.fX); - BitStream.Read(vecMoveSpeed.fY); - BitStream.Read(vecMoveSpeed.fZ); + if (ucFlags & 0x01) + { + BitStream.Read(vecPosition.fX); + BitStream.Read(vecPosition.fY); + BitStream.Read(vecPosition.fZ); + } + + if (ucFlags & 0x02) + BitStream.Read(fRotation); + + if (ucFlags & 0x04) + { + BitStream.Read(vecMoveSpeed.fX); + BitStream.Read(vecMoveSpeed.fY); + BitStream.Read(vecMoveSpeed.fZ); + } } // And health with armour @@ -223,9 +244,9 @@ void CPedSync::Packet_PedSync(NetBitStreamInterface& BitStream) if (pPed && pPed->CanUpdateSync(ucSyncTimeContext)) { if (ucFlags & 0x01) - pPed->SetPosition(vecPosition); + pPed->SetTargetPosition(vecPosition, PED_SYNC_RATE); if (ucFlags & 0x02) - pPed->SetCurrentRotation(fRotation); + pPed->SetTargetRotation(PED_SYNC_RATE, fRotation, 0.0f); if (ucFlags & 0x04) pPed->SetMoveSpeed(vecMoveSpeed); if (ucFlags & 0x08) @@ -303,24 +324,51 @@ void CPedSync::WritePedInformation(NetBitStreamInterface* pBitStream, CClientPed // Write position if needed if (ucFlags & 0x01) { - pBitStream->Write(vecPosition.fX); - pBitStream->Write(vecPosition.fY); - pBitStream->Write(vecPosition.fZ); + if (pBitStream->Can(eBitStreamVersion::PedSync_Revision)) + { + SPositionSync position(false); + position.data.vecPosition = vecPosition; + pBitStream->Write(&position); + } + else + { + pBitStream->Write(vecPosition.fX); + pBitStream->Write(vecPosition.fY); + pBitStream->Write(vecPosition.fZ); + } + pPed->m_LastSyncedData->vPosition = vecPosition; } if (ucFlags & 0x02) { - pBitStream->Write(pPed->GetCurrentRotation()); + if (pBitStream->Can(eBitStreamVersion::PedSync_Revision)) + { + SPedRotationSync rotation; + rotation.data.fRotation = pPed->GetCurrentRotation(); + pBitStream->Write(&rotation); + } + else + pBitStream->Write(pPed->GetCurrentRotation()); + pPed->m_LastSyncedData->fRotation = pPed->GetCurrentRotation(); } // Write velocity if (ucFlags & 0x04) { - pBitStream->Write(vecVelocity.fX); - pBitStream->Write(vecVelocity.fY); - pBitStream->Write(vecVelocity.fZ); + if (pBitStream->Can(eBitStreamVersion::PedSync_Revision)) + { + SVelocitySync velocity; + pBitStream->Write(&velocity); + } + else + { + pBitStream->Write(vecVelocity.fX); + pBitStream->Write(vecVelocity.fY); + pBitStream->Write(vecVelocity.fZ); + } + pPed->m_LastSyncedData->vVelocity = vecVelocity; } diff --git a/Server/mods/deathmatch/logic/CPedSync.cpp b/Server/mods/deathmatch/logic/CPedSync.cpp index 02260d0756..cb2f9e417b 100644 --- a/Server/mods/deathmatch/logic/CPedSync.cpp +++ b/Server/mods/deathmatch/logic/CPedSync.cpp @@ -234,13 +234,13 @@ void CPedSync::Packet_PedSync(CPedSyncPacket& Packet) // Apply the data to the ped if (Data.ucFlags & 0x01) { - pPed->SetPosition(Data.vecPosition); + pPed->SetPosition(Data.position.data.vecPosition); g_pGame->GetColManager()->DoHitDetection(pPed->GetPosition(), pPed); } if (Data.ucFlags & 0x02) - pPed->SetRotation(Data.fRotation); + pPed->SetRotation(Data.rotation.data.fRotation); if (Data.ucFlags & 0x04) - pPed->SetVelocity(Data.vecVelocity); + pPed->SetVelocity(Data.velocity.data.vecVelocity); if (Data.ucFlags & 0x08) { diff --git a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp index e71997aaf0..7af83dcb51 100644 --- a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp @@ -40,22 +40,8 @@ bool CPedSyncPacket::Read(NetBitStreamInterface& BitStream) // Did we recieve position? if (ucFlags & 0x01) - { - if (!BitStream.Read(Data.vecPosition.fX) || !BitStream.Read(Data.vecPosition.fY) || !BitStream.Read(Data.vecPosition.fZ)) - return false; - } - - // Rotation - if (ucFlags & 0x02) - { - if (!BitStream.Read(Data.fRotation)) - return false; - } - - // Velocity - if (ucFlags & 0x04) - { - if (!BitStream.Read(Data.vecVelocity.fX) || !BitStream.Read(Data.vecVelocity.fY) || !BitStream.Read(Data.vecVelocity.fZ)) + { + if (!(BitStream.Can(eBitStreamVersion::PedSync_Revision) ? Data.ReadSpatialData(BitStream) : Data.ReadSpatialDataBC(BitStream))) return false; } @@ -108,25 +94,39 @@ bool CPedSyncPacket::Write(NetBitStreamInterface& BitStream) const BitStream.Write(Data.ucFlags); - // Position and rotation - if (Data.ucFlags & 0x01) + if (BitStream.Can(eBitStreamVersion::PedSync_Revision)) { - BitStream.Write(Data.vecPosition.fX); - BitStream.Write(Data.vecPosition.fY); - BitStream.Write(Data.vecPosition.fZ); - } + // Position and rotation + if (Data.ucFlags & 0x01) + BitStream.Write(&Data.position); - if (Data.ucFlags & 0x02) - { - BitStream.Write(Data.fRotation); - } + if (Data.ucFlags & 0x02) + BitStream.Write(&Data.rotation); - // Velocity - if (Data.ucFlags & 0x04) + // Velocity + if (Data.ucFlags & 0x04) + BitStream.Write(&Data.velocity); + } + else { - BitStream.Write(Data.vecVelocity.fX); - BitStream.Write(Data.vecVelocity.fY); - BitStream.Write(Data.vecVelocity.fZ); + // Position and rotation + if (Data.ucFlags & 0x01) + { + BitStream.Write(Data.position.data.vecPosition.fX); + BitStream.Write(Data.position.data.vecPosition.fY); + BitStream.Write(Data.position.data.vecPosition.fZ); + } + + if (Data.ucFlags & 0x02) + BitStream.Write(Data.rotation.data.fRotation); + + // Velocity + if (Data.ucFlags & 0x04) + { + BitStream.Write(Data.velocity.data.vecVelocity.fX); + BitStream.Write(Data.velocity.data.vecVelocity.fY); + BitStream.Write(Data.velocity.data.vecVelocity.fZ); + } } // Health, armour, on fire and is in water @@ -141,3 +141,55 @@ bool CPedSyncPacket::Write(NetBitStreamInterface& BitStream) const return true; } + +bool CPedSyncPacket::SyncData::ReadSpatialData(NetBitStreamInterface& BitStream) +{ + // Did we recieve position? + if (ucFlags & 0x01) + { + if (!BitStream.Read(&position)) + return false; + } + + // Rotation + if (ucFlags & 0x02) + { + if (!BitStream.Read(&rotation)) + return false; + } + + // Velocity + if (ucFlags & 0x04) + { + if (!BitStream.Read(&velocity)) + return false; + } + + return true; +} + +bool CPedSyncPacket::SyncData::ReadSpatialDataBC(NetBitStreamInterface& BitStream) +{ + // Did we recieve position? + if (ucFlags & 0x01) + { + if (!BitStream.Read(position.data.vecPosition.fX) || !BitStream.Read(position.data.vecPosition.fY) || !BitStream.Read(position.data.vecPosition.fZ)) + return false; + } + + // Rotation + if (ucFlags & 0x02) + { + if (!BitStream.Read(rotation.data.fRotation)) + return false; + } + + // Velocity + if (ucFlags & 0x04) + { + if (!BitStream.Read(velocity.data.vecVelocity.fX) || !BitStream.Read(velocity.data.vecVelocity.fY) || !BitStream.Read(velocity.data.vecVelocity.fZ)) + return false; + } + + return true; +} diff --git a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h index ccea0de3a3..f200be509b 100644 --- a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h +++ b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h @@ -13,6 +13,7 @@ #include #include "CPacket.h" +#include #include class CPedSyncPacket final : public CPacket @@ -20,16 +21,20 @@ class CPedSyncPacket final : public CPacket public: struct SyncData { - ElementID ID; - unsigned char ucFlags; - unsigned char ucSyncTimeContext; - CVector vecPosition; - float fRotation; - CVector vecVelocity; - float fHealth; - float fArmor; - bool bOnFire; - bool bIsInWater; + ElementID ID; + unsigned char ucFlags; + unsigned char ucSyncTimeContext; + SPositionSync position; + SPedRotationSync rotation; + SVelocitySync velocity; + float fHealth; + float fArmor; + bool bOnFire; + bool bIsInWater; + + bool ReadSpatialData(NetBitStreamInterface& BitStream); + // Backward compatibility + bool ReadSpatialDataBC(NetBitStreamInterface& BitStream); }; public: diff --git a/Shared/mods/deathmatch/logic/Utils.h b/Shared/mods/deathmatch/logic/Utils.h index 3930514d80..33cd9d072a 100644 --- a/Shared/mods/deathmatch/logic/Utils.h +++ b/Shared/mods/deathmatch/logic/Utils.h @@ -233,6 +233,15 @@ inline float GetOffsetDegrees(float a, float b) c = (360.0f + c); return c; } +inline float GetOffsetRadians(float a, float b) +{ + float c = (b > a) ? b - a : 0.0f - (a - b); + if (c > PI) + c = 0.0f - (2 * PI - c); + else if (c <= -PI) + c = (2 * PI + c); + return c; +} // Assuming fValue is the result of a difference calculation, calculate // the shortest positive distance after wrapping diff --git a/Shared/sdk/CVector.h b/Shared/sdk/CVector.h index 265b186e9d..5c2ddde7a6 100644 --- a/Shared/sdk/CVector.h +++ b/Shared/sdk/CVector.h @@ -26,11 +26,15 @@ class CVector static constexpr float FLOAT_EPSILON = 0.0001f; public: - float fX = 0.0f; - float fY = 0.0f; - float fZ = 0.0f; + float fX; + float fY; + float fZ; - constexpr CVector() = default; + struct NoInit{}; + + CVector(NoInit) {} + + constexpr CVector() : fX(0.0f), fY(0.0f), fZ(0.0f) {} constexpr CVector(float x, float y, float z) : fX(x), fY(y), fZ(z) {} diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index bd33fcfcbf..9c32320d53 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -552,6 +552,10 @@ enum class eBitStreamVersion : unsigned short // 2024-05-31 BreakObject_Serverside, + // Ped syncronization revision + // 2024-06-16 + PedSync_Revision, + // This allows us to automatically increment the BitStreamVersion when things are added to this enum. // Make sure you only add things above this comment. Next,