diff --git a/dGame/dComponents/Activity/QuickBuildComponent.cpp b/dGame/dComponents/Activity/QuickBuildComponent.cpp index b4bba0e0f..6953773f1 100644 --- a/dGame/dComponents/Activity/QuickBuildComponent.cpp +++ b/dGame/dComponents/Activity/QuickBuildComponent.cpp @@ -162,7 +162,7 @@ void QuickBuildComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIni outBitStream.Write(m_ActivatorPosition); outBitStream.Write(m_RepositionPlayer); } - m_StateDirty = false; + if (!bIsInitialUpdate) m_StateDirty = false; } } diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 9c4f0a93f..85c288e88 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -259,13 +259,14 @@ void DestroyableComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIn if (m_ExplodeFactor != 1.0f) outBitStream.Write(m_ExplodeFactor); } } - m_DirtyHealth = false; + // A construction goes to one client; the players already watching still need a waiting change + if (!bIsInitialUpdate) m_DirtyHealth = false; } outBitStream.Write(m_DirtyThreatList || bIsInitialUpdate); if (m_DirtyThreatList || bIsInitialUpdate) { outBitStream.Write(m_HasThreats); - m_DirtyThreatList = false; + if (!bIsInitialUpdate) m_DirtyThreatList = false; } } diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index a16ee8aa5..495ece650 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -1048,7 +1048,8 @@ void InventoryComponent::Serialize(RakNet::BitStream& outBitStream, const bool b outBitStream.Write(item.bound); } - m_Dirty = false; + // A construction goes to one client; the players already watching still need a waiting equipment change + if (!bIsInitialUpdate) m_Dirty = false; } else { outBitStream.Write(false); } diff --git a/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp b/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp index 70678c55b..63382366b 100644 --- a/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp +++ b/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp @@ -622,6 +622,28 @@ TEST_F(DestroyableTest, PlayerDieDoesNotClaimAClientDeath) { player.SetCharacter(nullptr); } +// A construction goes to the one client the object came into range of; it must not use up the health change the +// players already watching are waiting for (LWODestroyableComponent::Deserialize reads it behind a flag bit). +TEST_F(DestroyableTest, AConstructionKeepsThePendingHealthChange) { + destroyableComponent->SetHealth(3); + RakNet::BitStream construction; + destroyableComponent->Serialize(construction, true); + + RakNet::BitStream update; + destroyableComponent->Serialize(update, false); + bool hasHealth{}; + uint32_t health{}; + ASSERT_TRUE(update.Read(hasHealth)); + ASSERT_TRUE(hasHealth); + ASSERT_TRUE(update.Read(health)); + EXPECT_EQ(health, 3u); + + // Written once + RakNet::BitStream again; + destroyableComponent->Serialize(again, false); + EXPECT_EQ(again.GetNumberOfBitsUsed(), 2u); +} + // LWOCharacterComponent::SendMessage, IsValidPVPTarget: two players with PVP on are enemies, a player is never its own TEST_F(DestroyableTest, APlayerWithPvpIsNotItsOwnEnemy) { auto playerInfo = info; diff --git a/tests/dGameTests/dComponentsTests/ReplicaConstructionTests.cpp b/tests/dGameTests/dComponentsTests/ReplicaConstructionTests.cpp index 2fc054ddb..9d8846b9e 100644 --- a/tests/dGameTests/dComponentsTests/ReplicaConstructionTests.cpp +++ b/tests/dGameTests/dComponentsTests/ReplicaConstructionTests.cpp @@ -700,6 +700,11 @@ TEST_F(InventoryConstructionTest, NpcItemsLikeLive) { coleExpected.Write(0); ExpectSameBits(coleConstruction, coleExpected); + // The equipment put on before the construction still goes to the clients already watching, once + RakNet::BitStream pending; + coleInventory->Serialize(pending, false); + EXPECT_GT(pending.GetNumberOfBitsUsed(), 2u); + // A serialization with nothing changed writes neither list RakNet::BitStream serialization; coleInventory->Serialize(serialization, false);