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
This commit is contained in:
David Markowitz 2024-02-27 21:40:26 -08:00 committed by GitHub
parent 398426545c
commit ef3fdba621
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 41 additions and 125 deletions

View File

@ -6,28 +6,14 @@
struct RemoteInputInfo { 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) { 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; 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_RemoteInputX = 0;
float m_RemoteInputY; float m_RemoteInputY = 0;
bool m_IsPowersliding; bool m_IsPowersliding = false;
bool m_IsModified; bool m_IsModified = false;
}; };
struct LocalSpaceInfo { struct LocalSpaceInfo {

View File

@ -2126,9 +2126,7 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) {
havokVehiclePhysicsComponent->SetIsOnGround(update.onGround); havokVehiclePhysicsComponent->SetIsOnGround(update.onGround);
havokVehiclePhysicsComponent->SetIsOnRail(update.onRail); havokVehiclePhysicsComponent->SetIsOnRail(update.onRail);
havokVehiclePhysicsComponent->SetVelocity(update.velocity); havokVehiclePhysicsComponent->SetVelocity(update.velocity);
havokVehiclePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO);
havokVehiclePhysicsComponent->SetAngularVelocity(update.angularVelocity); havokVehiclePhysicsComponent->SetAngularVelocity(update.angularVelocity);
havokVehiclePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO);
havokVehiclePhysicsComponent->SetRemoteInputInfo(update.remoteInputInfo); havokVehiclePhysicsComponent->SetRemoteInputInfo(update.remoteInputInfo);
} else { } else {
// Need to get the mount's controllable physics // Need to get the mount's controllable physics
@ -2139,9 +2137,7 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) {
possessedControllablePhysicsComponent->SetIsOnGround(update.onGround); possessedControllablePhysicsComponent->SetIsOnGround(update.onGround);
possessedControllablePhysicsComponent->SetIsOnRail(update.onRail); possessedControllablePhysicsComponent->SetIsOnRail(update.onRail);
possessedControllablePhysicsComponent->SetVelocity(update.velocity); possessedControllablePhysicsComponent->SetVelocity(update.velocity);
possessedControllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO);
possessedControllablePhysicsComponent->SetAngularVelocity(update.angularVelocity); possessedControllablePhysicsComponent->SetAngularVelocity(update.angularVelocity);
possessedControllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO);
} }
Game::entityManager->SerializeEntity(possassableEntity); Game::entityManager->SerializeEntity(possassableEntity);
} }
@ -2163,9 +2159,7 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) {
controllablePhysicsComponent->SetIsOnGround(update.onGround); controllablePhysicsComponent->SetIsOnGround(update.onGround);
controllablePhysicsComponent->SetIsOnRail(update.onRail); controllablePhysicsComponent->SetIsOnRail(update.onRail);
controllablePhysicsComponent->SetVelocity(update.velocity); controllablePhysicsComponent->SetVelocity(update.velocity);
controllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO);
controllablePhysicsComponent->SetAngularVelocity(update.angularVelocity); controllablePhysicsComponent->SetAngularVelocity(update.angularVelocity);
controllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO);
auto* ghostComponent = GetComponent<GhostComponent>(); auto* ghostComponent = GetComponent<GhostComponent>();
if (ghostComponent) ghostComponent->SetGhostReferencePoint(update.position); if (ghostComponent) ghostComponent->SetGhostReferencePoint(update.position);

View File

@ -21,8 +21,6 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Phy
m_InJetpackMode = false; m_InJetpackMode = false;
m_IsOnGround = true; m_IsOnGround = true;
m_IsOnRail = false; m_IsOnRail = false;
m_DirtyVelocity = true;
m_DirtyAngularVelocity = true;
m_dpEntity = nullptr; m_dpEntity = nullptr;
m_Static = false; m_Static = false;
m_SpeedMultiplier = 1; m_SpeedMultiplier = 1;
@ -135,27 +133,29 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
outBitStream.Write(m_IsOnGround); outBitStream.Write(m_IsOnGround);
outBitStream.Write(m_IsOnRail); outBitStream.Write(m_IsOnRail);
outBitStream.Write(m_DirtyVelocity); bool isNotZero = m_Velocity != NiPoint3Constant::ZERO;
if (m_DirtyVelocity) { outBitStream.Write(isNotZero);
if (isNotZero) {
outBitStream.Write(m_Velocity.x); outBitStream.Write(m_Velocity.x);
outBitStream.Write(m_Velocity.y); outBitStream.Write(m_Velocity.y);
outBitStream.Write(m_Velocity.z); outBitStream.Write(m_Velocity.z);
} }
outBitStream.Write(m_DirtyAngularVelocity); isNotZero = m_AngularVelocity != NiPoint3Constant::ZERO;
if (m_DirtyAngularVelocity) { outBitStream.Write(isNotZero);
if (isNotZero) {
outBitStream.Write(m_AngularVelocity.x); outBitStream.Write(m_AngularVelocity.x);
outBitStream.Write(m_AngularVelocity.y); outBitStream.Write(m_AngularVelocity.y);
outBitStream.Write(m_AngularVelocity.z); outBitStream.Write(m_AngularVelocity.z);
} }
outBitStream.Write0(); outBitStream.Write0();
}
if (!bIsInitialUpdate) { if (!bIsInitialUpdate) {
m_DirtyPosition = false;
outBitStream.Write(m_IsTeleporting); outBitStream.Write(m_IsTeleporting);
m_IsTeleporting = false; m_IsTeleporting = false;
} }
}
} }
void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
@ -211,33 +211,29 @@ void ControllablePhysicsComponent::SetRotation(const NiQuaternion& rot) {
} }
void ControllablePhysicsComponent::SetVelocity(const NiPoint3& vel) { void ControllablePhysicsComponent::SetVelocity(const NiPoint3& vel) {
if (m_Static) { if (m_Static || m_Velocity == vel) return;
return;
}
m_Velocity = vel; m_Velocity = vel;
m_DirtyPosition = true; m_DirtyPosition = true;
m_DirtyVelocity = true;
if (m_dpEntity) m_dpEntity->SetVelocity(vel); if (m_dpEntity) m_dpEntity->SetVelocity(vel);
} }
void ControllablePhysicsComponent::SetAngularVelocity(const NiPoint3& vel) { void ControllablePhysicsComponent::SetAngularVelocity(const NiPoint3& vel) {
if (m_Static) { if (m_Static || m_AngularVelocity == vel) return;
return;
}
m_AngularVelocity = vel; m_AngularVelocity = vel;
m_DirtyPosition = true; m_DirtyPosition = true;
m_DirtyAngularVelocity = true;
} }
void ControllablePhysicsComponent::SetIsOnGround(bool val) { void ControllablePhysicsComponent::SetIsOnGround(bool val) {
if (m_IsOnGround == val) return;
m_DirtyPosition = true; m_DirtyPosition = true;
m_IsOnGround = val; m_IsOnGround = val;
} }
void ControllablePhysicsComponent::SetIsOnRail(bool val) { void ControllablePhysicsComponent::SetIsOnRail(bool val) {
if (m_IsOnRail == val) return;
m_DirtyPosition = true; m_DirtyPosition = true;
m_IsOnRail = val; m_IsOnRail = val;
} }
@ -245,15 +241,6 @@ void ControllablePhysicsComponent::SetIsOnRail(bool val) {
void ControllablePhysicsComponent::SetDirtyPosition(bool val) { void ControllablePhysicsComponent::SetDirtyPosition(bool val) {
m_DirtyPosition = 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) { void ControllablePhysicsComponent::AddPickupRadiusScale(float value) {
m_ActivePickupRadiusScales.push_back(value); m_ActivePickupRadiusScales.push_back(value);
if (value > m_PickupRadius) { if (value > m_PickupRadius) {
@ -309,7 +296,7 @@ void ControllablePhysicsComponent::RemoveSpeedboost(float value) {
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
} }
void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bool specialAnims){ void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bool specialAnims) {
if (m_IsInBubble) { if (m_IsInBubble) {
LOG("Already in bubble"); LOG("Already in bubble");
return; return;
@ -321,7 +308,7 @@ void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bo
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
} }
void ControllablePhysicsComponent::DeactivateBubbleBuff(){ void ControllablePhysicsComponent::DeactivateBubbleBuff() {
m_DirtyBubble = true; m_DirtyBubble = true;
m_IsInBubble = false; m_IsInBubble = false;
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
@ -336,9 +323,9 @@ void ControllablePhysicsComponent::SetStunImmunity(
const bool bImmuneToStunJump, const bool bImmuneToStunJump,
const bool bImmuneToStunMove, const bool bImmuneToStunMove,
const bool bImmuneToStunTurn, 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 (bImmuneToStunAttack && m_ImmuneToStunAttackCount > 0) m_ImmuneToStunAttackCount -= 1;
if (bImmuneToStunEquip && m_ImmuneToStunEquipCount > 0) m_ImmuneToStunEquipCount -= 1; if (bImmuneToStunEquip && m_ImmuneToStunEquipCount > 0) m_ImmuneToStunEquipCount -= 1;
if (bImmuneToStunInteract && m_ImmuneToStunInteractCount > 0) m_ImmuneToStunInteractCount -= 1; if (bImmuneToStunInteract && m_ImmuneToStunInteractCount > 0) m_ImmuneToStunInteractCount -= 1;

View File

@ -104,18 +104,6 @@ public:
*/ */
void SetDirtyPosition(bool val); 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 * Sets whether or not the entity is currently wearing a jetpack
* @param val 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; 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 * The current velocity of the entity
*/ */
NiPoint3 m_Velocity; NiPoint3 m_Velocity;
/**
* Whether or not the angular velocity is dirty, forcing a serialization
*/
bool m_DirtyAngularVelocity;
/** /**
* The current angular velocity of the entity * The current angular velocity of the entity
*/ */

View File

@ -7,8 +7,6 @@ HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent) : Phy
m_IsOnGround = true; m_IsOnGround = true;
m_IsOnRail = false; m_IsOnRail = false;
m_DirtyPosition = true; m_DirtyPosition = true;
m_DirtyVelocity = true;
m_DirtyAngularVelocity = true;
m_EndBehavior = GeneralUtils::GenerateRandomNumber<uint32_t>(0, 7); m_EndBehavior = GeneralUtils::GenerateRandomNumber<uint32_t>(0, 7);
} }
@ -37,17 +35,9 @@ void HavokVehiclePhysicsComponent::SetIsOnRail(bool val) {
} }
void HavokVehiclePhysicsComponent::SetRemoteInputInfo(const RemoteInputInfo& remoteInputInfo) { void HavokVehiclePhysicsComponent::SetRemoteInputInfo(const RemoteInputInfo& remoteInputInfo) {
if (m_RemoteInputInfo == remoteInputInfo) return; if (remoteInputInfo == m_RemoteInputInfo) return;
this->m_RemoteInputInfo = remoteInputInfo; this->m_RemoteInputInfo = remoteInputInfo;
m_DirtyRemoteInput = true; m_DirtyPosition = true;
}
void HavokVehiclePhysicsComponent::SetDirtyVelocity(bool val) {
m_DirtyVelocity = val;
}
void HavokVehiclePhysicsComponent::SetDirtyAngularVelocity(bool val) {
m_DirtyAngularVelocity = val;
} }
void HavokVehiclePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) { 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_IsOnGround);
outBitStream.Write(m_IsOnRail); outBitStream.Write(m_IsOnRail);
outBitStream.Write(bIsInitialUpdate || m_DirtyVelocity); bool isNotZero = m_Velocity != NiPoint3Constant::ZERO;
outBitStream.Write(isNotZero);
if (bIsInitialUpdate || m_DirtyVelocity) { if (isNotZero) {
outBitStream.Write(m_Velocity.x); outBitStream.Write(m_Velocity.x);
outBitStream.Write(m_Velocity.y); outBitStream.Write(m_Velocity.y);
outBitStream.Write(m_Velocity.z); outBitStream.Write(m_Velocity.z);
m_DirtyVelocity = false;
} }
outBitStream.Write(bIsInitialUpdate || m_DirtyAngularVelocity); isNotZero = m_AngularVelocity != NiPoint3Constant::ZERO;
outBitStream.Write(isNotZero);
if (bIsInitialUpdate || m_DirtyAngularVelocity) { if (isNotZero) {
outBitStream.Write(m_AngularVelocity.x); outBitStream.Write(m_AngularVelocity.x);
outBitStream.Write(m_AngularVelocity.y); outBitStream.Write(m_AngularVelocity.y);
outBitStream.Write(m_AngularVelocity.z); outBitStream.Write(m_AngularVelocity.z);
m_DirtyAngularVelocity = false;
} }
outBitStream.Write0(); // local_space_info. TODO: Implement this outBitStream.Write0(); // local_space_info. TODO: Implement this
outBitStream.Write(m_DirtyRemoteInput || bIsInitialUpdate); // remote_input_info // This structure only has this bool flag set to false if a ptr to the peVehicle is null, which we don't have
if (m_DirtyRemoteInput || bIsInitialUpdate) { // 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_RemoteInputX);
outBitStream.Write(m_RemoteInputInfo.m_RemoteInputY); outBitStream.Write(m_RemoteInputInfo.m_RemoteInputY);
outBitStream.Write(m_RemoteInputInfo.m_IsPowersliding); outBitStream.Write(m_RemoteInputInfo.m_IsPowersliding);
outBitStream.Write(m_RemoteInputInfo.m_IsModified); outBitStream.Write(m_RemoteInputInfo.m_IsModified);
m_DirtyRemoteInput = false;
}
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. 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(); outBitStream.Write0();
} }
void HavokVehiclePhysicsComponent::Update(float deltaTime) {
if (m_SoftUpdate > 5) {
Game::entityManager->SerializeEntity(m_Parent);
m_SoftUpdate = 0;
} else {
m_SoftUpdate += deltaTime;
}
}

View File

@ -17,8 +17,6 @@ public:
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override; void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void Update(float deltaTime) override;
/** /**
* Sets the velocity * Sets the velocity
* @param vel the new velocity * @param vel the new velocity
@ -67,22 +65,16 @@ public:
*/ */
const bool GetIsOnRail() const { return m_IsOnRail; } const bool GetIsOnRail() const { return m_IsOnRail; }
void SetDirtyPosition(bool val);
void SetDirtyVelocity(bool val);
void SetDirtyAngularVelocity(bool val);
void SetRemoteInputInfo(const RemoteInputInfo&); void SetRemoteInputInfo(const RemoteInputInfo&);
private: private:
bool m_DirtyVelocity;
NiPoint3 m_Velocity; NiPoint3 m_Velocity;
bool m_DirtyAngularVelocity;
NiPoint3 m_AngularVelocity; NiPoint3 m_AngularVelocity;
bool m_IsOnGround; bool m_IsOnGround;
bool m_IsOnRail; bool m_IsOnRail;
float m_SoftUpdate = 0; float m_SoftUpdate = 0;
uint32_t m_EndBehavior; uint32_t m_EndBehavior;
RemoteInputInfo m_RemoteInputInfo; RemoteInputInfo m_RemoteInputInfo;
bool m_DirtyRemoteInput;
}; };