mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-11-14 15:57:13 +00:00
fix: constructions keep pending health, quick build and equipment changes
The destroyable's health and threat blocks, the quick build's state and the inventory's equipped items are each read behind a flag bit (LWODestroyableComponent::Deserialize 0x00d2bbd0 and the others). DLU cleared their dirty flags when it wrote a construction, which goes only to the client the object came into range of, so a change waiting for the next update never reached the clients already watching: a health bar, a quick build's state, a player's new gear. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -700,6 +700,11 @@ TEST_F(InventoryConstructionTest, NpcItemsLikeLive) {
|
||||
coleExpected.Write<uint32_t>(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);
|
||||
|
||||
Reference in New Issue
Block a user