From ef3fdba6211fd0279f9360b954e7509a108df2ff Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 27 Feb 2024 21:40:26 -0800 Subject: [PATCH] fix: FrameStats serialization (#1481) * fix serialization Was incorrect before. The only flags are if any data in the FrameStats has changed, you write them again. Velocities also do not use dirty flags for their values, they use a flag to determine if their velocity if zero or non-zero. if any velocity changes, re-write FrameStats. Tested that 2 players can see each other move as before, enemies move as before and players racing is identical as before. * Update HavokVehiclePhysicsComponent.cpp --- dCommon/PositionUpdate.h | 22 ++------ dGame/Entity.cpp | 8 +-- .../ControllablePhysicsComponent.cpp | 51 +++++++----------- .../ControllablePhysicsComponent.h | 22 -------- .../HavokVehiclePhysicsComponent.cpp | 53 ++++++------------- .../HavokVehiclePhysicsComponent.h | 10 +--- 6 files changed, 41 insertions(+), 125 deletions(-) diff --git a/dCommon/PositionUpdate.h b/dCommon/PositionUpdate.h index 4d591a97..f28c682d 100644 --- a/dCommon/PositionUpdate.h +++ b/dCommon/PositionUpdate.h @@ -6,28 +6,14 @@ struct RemoteInputInfo { - RemoteInputInfo() { - m_RemoteInputX = 0; - m_RemoteInputY = 0; - m_IsPowersliding = false; - m_IsModified = false; - } - - void operator=(const RemoteInputInfo& other) { - m_RemoteInputX = other.m_RemoteInputX; - m_RemoteInputY = other.m_RemoteInputY; - m_IsPowersliding = other.m_IsPowersliding; - m_IsModified = other.m_IsModified; - } - bool operator==(const RemoteInputInfo& other) { return m_RemoteInputX == other.m_RemoteInputX && m_RemoteInputY == other.m_RemoteInputY && m_IsPowersliding == other.m_IsPowersliding && m_IsModified == other.m_IsModified; } - float m_RemoteInputX; - float m_RemoteInputY; - bool m_IsPowersliding; - bool m_IsModified; + float m_RemoteInputX = 0; + float m_RemoteInputY = 0; + bool m_IsPowersliding = false; + bool m_IsModified = false; }; struct LocalSpaceInfo { diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 55b2b85f..be8d8b10 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -2126,9 +2126,7 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) { havokVehiclePhysicsComponent->SetIsOnGround(update.onGround); havokVehiclePhysicsComponent->SetIsOnRail(update.onRail); havokVehiclePhysicsComponent->SetVelocity(update.velocity); - havokVehiclePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO); havokVehiclePhysicsComponent->SetAngularVelocity(update.angularVelocity); - havokVehiclePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO); havokVehiclePhysicsComponent->SetRemoteInputInfo(update.remoteInputInfo); } else { // Need to get the mount's controllable physics @@ -2139,9 +2137,7 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) { possessedControllablePhysicsComponent->SetIsOnGround(update.onGround); possessedControllablePhysicsComponent->SetIsOnRail(update.onRail); possessedControllablePhysicsComponent->SetVelocity(update.velocity); - possessedControllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO); possessedControllablePhysicsComponent->SetAngularVelocity(update.angularVelocity); - possessedControllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO); } Game::entityManager->SerializeEntity(possassableEntity); } @@ -2163,9 +2159,7 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) { controllablePhysicsComponent->SetIsOnGround(update.onGround); controllablePhysicsComponent->SetIsOnRail(update.onRail); controllablePhysicsComponent->SetVelocity(update.velocity); - controllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO); controllablePhysicsComponent->SetAngularVelocity(update.angularVelocity); - controllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO); auto* ghostComponent = GetComponent(); if (ghostComponent) ghostComponent->SetGhostReferencePoint(update.position); @@ -2202,4 +2196,4 @@ void Entity::SetScale(const float scale) { if (scale == m_Scale) return; m_Scale = scale; Game::entityManager->SerializeEntity(this); -} \ No newline at end of file +} diff --git a/dGame/dComponents/ControllablePhysicsComponent.cpp b/dGame/dComponents/ControllablePhysicsComponent.cpp index daa14ac3..99b51af8 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.cpp +++ b/dGame/dComponents/ControllablePhysicsComponent.cpp @@ -21,8 +21,6 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Phy m_InJetpackMode = false; m_IsOnGround = true; m_IsOnRail = false; - m_DirtyVelocity = true; - m_DirtyAngularVelocity = true; m_dpEntity = nullptr; m_Static = false; m_SpeedMultiplier = 1; @@ -135,26 +133,28 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo outBitStream.Write(m_IsOnGround); outBitStream.Write(m_IsOnRail); - outBitStream.Write(m_DirtyVelocity); - if (m_DirtyVelocity) { + bool isNotZero = m_Velocity != NiPoint3Constant::ZERO; + outBitStream.Write(isNotZero); + if (isNotZero) { outBitStream.Write(m_Velocity.x); outBitStream.Write(m_Velocity.y); outBitStream.Write(m_Velocity.z); } - outBitStream.Write(m_DirtyAngularVelocity); - if (m_DirtyAngularVelocity) { + isNotZero = m_AngularVelocity != NiPoint3Constant::ZERO; + outBitStream.Write(isNotZero); + if (isNotZero) { outBitStream.Write(m_AngularVelocity.x); outBitStream.Write(m_AngularVelocity.y); outBitStream.Write(m_AngularVelocity.z); } outBitStream.Write0(); - } - - if (!bIsInitialUpdate) { - outBitStream.Write(m_IsTeleporting); - m_IsTeleporting = false; + if (!bIsInitialUpdate) { + m_DirtyPosition = false; + outBitStream.Write(m_IsTeleporting); + m_IsTeleporting = false; + } } } @@ -211,33 +211,29 @@ void ControllablePhysicsComponent::SetRotation(const NiQuaternion& rot) { } void ControllablePhysicsComponent::SetVelocity(const NiPoint3& vel) { - if (m_Static) { - return; - } + if (m_Static || m_Velocity == vel) return; m_Velocity = vel; m_DirtyPosition = true; - m_DirtyVelocity = true; if (m_dpEntity) m_dpEntity->SetVelocity(vel); } void ControllablePhysicsComponent::SetAngularVelocity(const NiPoint3& vel) { - if (m_Static) { - return; - } + if (m_Static || m_AngularVelocity == vel) return; m_AngularVelocity = vel; m_DirtyPosition = true; - m_DirtyAngularVelocity = true; } void ControllablePhysicsComponent::SetIsOnGround(bool val) { + if (m_IsOnGround == val) return; m_DirtyPosition = true; m_IsOnGround = val; } void ControllablePhysicsComponent::SetIsOnRail(bool val) { + if (m_IsOnRail == val) return; m_DirtyPosition = true; m_IsOnRail = val; } @@ -245,15 +241,6 @@ void ControllablePhysicsComponent::SetIsOnRail(bool val) { void ControllablePhysicsComponent::SetDirtyPosition(bool val) { m_DirtyPosition = val; } - -void ControllablePhysicsComponent::SetDirtyVelocity(bool val) { - m_DirtyVelocity = val; -} - -void ControllablePhysicsComponent::SetDirtyAngularVelocity(bool val) { - m_DirtyAngularVelocity = val; -} - void ControllablePhysicsComponent::AddPickupRadiusScale(float value) { m_ActivePickupRadiusScales.push_back(value); if (value > m_PickupRadius) { @@ -309,7 +296,7 @@ void ControllablePhysicsComponent::RemoveSpeedboost(float value) { Game::entityManager->SerializeEntity(m_Parent); } -void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bool specialAnims){ +void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bool specialAnims) { if (m_IsInBubble) { LOG("Already in bubble"); return; @@ -321,7 +308,7 @@ void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bo Game::entityManager->SerializeEntity(m_Parent); } -void ControllablePhysicsComponent::DeactivateBubbleBuff(){ +void ControllablePhysicsComponent::DeactivateBubbleBuff() { m_DirtyBubble = true; m_IsInBubble = false; Game::entityManager->SerializeEntity(m_Parent); @@ -336,9 +323,9 @@ void ControllablePhysicsComponent::SetStunImmunity( const bool bImmuneToStunJump, const bool bImmuneToStunMove, const bool bImmuneToStunTurn, - const bool bImmuneToStunUseItem){ + const bool bImmuneToStunUseItem) { - if (state == eStateChangeType::POP){ + if (state == eStateChangeType::POP) { if (bImmuneToStunAttack && m_ImmuneToStunAttackCount > 0) m_ImmuneToStunAttackCount -= 1; if (bImmuneToStunEquip && m_ImmuneToStunEquipCount > 0) m_ImmuneToStunEquipCount -= 1; if (bImmuneToStunInteract && m_ImmuneToStunInteractCount > 0) m_ImmuneToStunInteractCount -= 1; diff --git a/dGame/dComponents/ControllablePhysicsComponent.h b/dGame/dComponents/ControllablePhysicsComponent.h index 313f80de..a0cc6aef 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.h +++ b/dGame/dComponents/ControllablePhysicsComponent.h @@ -104,18 +104,6 @@ public: */ void SetDirtyPosition(bool val); - /** - * Mark the velocity as dirty, forcing a serializtion update next tick - * @param val whether or not the velocity is dirty - */ - void SetDirtyVelocity(bool val); - - /** - * Mark the angular velocity as dirty, forcing a serialization update next tick - * @param val whether or not the angular velocity is dirty - */ - void SetDirtyAngularVelocity(bool val); - /** * Sets whether or not the entity is currently wearing a jetpack * @param val whether or not the entity is currently wearing a jetpack @@ -310,21 +298,11 @@ private: */ dpEntity* m_dpEntity; - /** - * Whether or not the velocity is dirty, forcing a serialization of the velocity - */ - bool m_DirtyVelocity; - /** * The current velocity of the entity */ NiPoint3 m_Velocity; - /** - * Whether or not the angular velocity is dirty, forcing a serialization - */ - bool m_DirtyAngularVelocity; - /** * The current angular velocity of the entity */ diff --git a/dGame/dComponents/HavokVehiclePhysicsComponent.cpp b/dGame/dComponents/HavokVehiclePhysicsComponent.cpp index 464cb357..635830cc 100644 --- a/dGame/dComponents/HavokVehiclePhysicsComponent.cpp +++ b/dGame/dComponents/HavokVehiclePhysicsComponent.cpp @@ -7,8 +7,6 @@ HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent) : Phy m_IsOnGround = true; m_IsOnRail = false; m_DirtyPosition = true; - m_DirtyVelocity = true; - m_DirtyAngularVelocity = true; m_EndBehavior = GeneralUtils::GenerateRandomNumber(0, 7); } @@ -37,17 +35,9 @@ void HavokVehiclePhysicsComponent::SetIsOnRail(bool val) { } void HavokVehiclePhysicsComponent::SetRemoteInputInfo(const RemoteInputInfo& remoteInputInfo) { - if (m_RemoteInputInfo == remoteInputInfo) return; + if (remoteInputInfo == m_RemoteInputInfo) return; this->m_RemoteInputInfo = remoteInputInfo; - m_DirtyRemoteInput = true; -} - -void HavokVehiclePhysicsComponent::SetDirtyVelocity(bool val) { - m_DirtyVelocity = val; -} - -void HavokVehiclePhysicsComponent::SetDirtyAngularVelocity(bool val) { - m_DirtyAngularVelocity = val; + m_DirtyPosition = true; } void HavokVehiclePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) { @@ -67,34 +57,32 @@ void HavokVehiclePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo outBitStream.Write(m_IsOnGround); outBitStream.Write(m_IsOnRail); - outBitStream.Write(bIsInitialUpdate || m_DirtyVelocity); - - if (bIsInitialUpdate || m_DirtyVelocity) { + bool isNotZero = m_Velocity != NiPoint3Constant::ZERO; + outBitStream.Write(isNotZero); + if (isNotZero) { outBitStream.Write(m_Velocity.x); outBitStream.Write(m_Velocity.y); outBitStream.Write(m_Velocity.z); - m_DirtyVelocity = false; } - outBitStream.Write(bIsInitialUpdate || m_DirtyAngularVelocity); - - if (bIsInitialUpdate || m_DirtyAngularVelocity) { + isNotZero = m_AngularVelocity != NiPoint3Constant::ZERO; + outBitStream.Write(isNotZero); + if (isNotZero) { outBitStream.Write(m_AngularVelocity.x); outBitStream.Write(m_AngularVelocity.y); outBitStream.Write(m_AngularVelocity.z); - m_DirtyAngularVelocity = false; } outBitStream.Write0(); // local_space_info. TODO: Implement this - outBitStream.Write(m_DirtyRemoteInput || bIsInitialUpdate); // remote_input_info - if (m_DirtyRemoteInput || bIsInitialUpdate) { - outBitStream.Write(m_RemoteInputInfo.m_RemoteInputX); - outBitStream.Write(m_RemoteInputInfo.m_RemoteInputY); - outBitStream.Write(m_RemoteInputInfo.m_IsPowersliding); - outBitStream.Write(m_RemoteInputInfo.m_IsModified); - m_DirtyRemoteInput = false; - } + // This structure only has this bool flag set to false if a ptr to the peVehicle is null, which we don't have + // therefore, this will always be 1, even if all the values in the structure are 0. + outBitStream.Write1(); // has remote_input_info + outBitStream.Write(m_RemoteInputInfo.m_RemoteInputX); + outBitStream.Write(m_RemoteInputInfo.m_RemoteInputY); + outBitStream.Write(m_RemoteInputInfo.m_IsPowersliding); + outBitStream.Write(m_RemoteInputInfo.m_IsModified); + outBitStream.Write(125.0f); // remote_input_ping TODO: Figure out how this should be calculated as it seems to be constant through the whole race. @@ -110,12 +98,3 @@ void HavokVehiclePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo outBitStream.Write0(); } - -void HavokVehiclePhysicsComponent::Update(float deltaTime) { - if (m_SoftUpdate > 5) { - Game::entityManager->SerializeEntity(m_Parent); - m_SoftUpdate = 0; - } else { - m_SoftUpdate += deltaTime; - } -} diff --git a/dGame/dComponents/HavokVehiclePhysicsComponent.h b/dGame/dComponents/HavokVehiclePhysicsComponent.h index 94c14ec6..83eb82fe 100644 --- a/dGame/dComponents/HavokVehiclePhysicsComponent.h +++ b/dGame/dComponents/HavokVehiclePhysicsComponent.h @@ -17,8 +17,6 @@ public: void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override; - void Update(float deltaTime) override; - /** * Sets the velocity * @param vel the new velocity @@ -67,22 +65,16 @@ public: */ const bool GetIsOnRail() const { return m_IsOnRail; } - void SetDirtyPosition(bool val); - void SetDirtyVelocity(bool val); - void SetDirtyAngularVelocity(bool val); void SetRemoteInputInfo(const RemoteInputInfo&); private: - bool m_DirtyVelocity; NiPoint3 m_Velocity; - - bool m_DirtyAngularVelocity; NiPoint3 m_AngularVelocity; + bool m_IsOnGround; bool m_IsOnRail; float m_SoftUpdate = 0; uint32_t m_EndBehavior; RemoteInputInfo m_RemoteInputInfo; - bool m_DirtyRemoteInput; };