fix: a phantom physics construction keeps the pending effect change

LWOPhantomPhysicsComponent::Deserialize (0x00c34db0) reads the effect
behind a flag bit. DLU cleared the dirty flag when it wrote a
construction, which goes only to the client the volume came into range
of, so the clients already watching it never got an effect change that
was waiting for the next update.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-11-10 13:19:28 -06:00
parent 5832567bc4
commit 599f33d436
2 changed files with 24 additions and 1 deletions

View File

@@ -153,7 +153,8 @@ void PhantomPhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bool bI
}
}
m_EffectInfoDirty = false;
// A construction goes to the one client the volume came into range of; the others still need the change
if (!bIsInitialUpdate) m_EffectInfoDirty = false;
}
}

View File

@@ -316,6 +316,28 @@ TEST_F(ReplicaConstructionTest, PhantomPhysicsVolumeEffectsAsLive) {
EXPECT_FALSE(effect.isDirectional);
}
// A construction (the volume coming into one player's range) doesn't use up an effect change the players already
// watching it still have to get.
TEST_F(ReplicaConstructionTest, PhantomPhysicsConstructionKeepsThePendingEffect) {
ConnectRegistry();
Entity volume(1007, info);
auto* const phantom = volume.AddComponent<PhantomPhysicsComponent>(-1);
RakNet::BitStream first;
phantom->Serialize(first, false);
const auto idle = first.GetNumberOfBitsUsed();
phantom->SetVolumeEffect({ "Friction", "0" });
RakNet::BitStream construction;
phantom->Serialize(construction, true);
RakNet::BitStream update;
phantom->Serialize(update, false);
EXPECT_EQ(update.GetNumberOfBitsUsed(), 2u + 1 + 32 + 32 + 1 + 1);
RakNet::BitStream again;
phantom->Serialize(again, false);
EXPECT_EQ(again.GetNumberOfBitsUsed(), 2u);
EXPECT_LE(again.GetNumberOfBitsUsed(), idle);
}
// A guild change (docs/Guilds.md) is written once: the client reads guild id, a u8 length and 16-bit characters, and
// redraws the name billboard every time it reads a name.
TEST_F(ReplicaConstructionTest, CharacterGuildChangeIsWrittenOnce) {