diff --git a/dGame/dComponents/LUPExhibitComponent.cpp b/dGame/dComponents/LUPExhibitComponent.cpp index 2680b0b2b..69315672a 100644 --- a/dGame/dComponents/LUPExhibitComponent.cpp +++ b/dGame/dComponents/LUPExhibitComponent.cpp @@ -16,8 +16,11 @@ void LUPExhibitComponent::NextLUPExhibit() { } void LUPExhibitComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) { - outBitStream.Write(m_DirtyLUPExhibit); - if (m_DirtyLUPExhibit) { + // LWOLUPExhibitComponent::Deserialize (0x00c63790) only learns the exhibit from this block, so a client the object + // comes into range of gets it too + const bool writeExhibit = bIsInitialUpdate || m_DirtyLUPExhibit; + outBitStream.Write(writeExhibit); + if (writeExhibit) { outBitStream.Write(m_LUPExhibits[m_LUPExhibitIndex % m_LUPExhibits.size()]); if (!bIsInitialUpdate) m_DirtyLUPExhibit = false; } diff --git a/tests/dGameTests/dComponentsTests/ReplicaConstructionTests.cpp b/tests/dGameTests/dComponentsTests/ReplicaConstructionTests.cpp index b0e9b7970..2fc054ddb 100644 --- a/tests/dGameTests/dComponentsTests/ReplicaConstructionTests.cpp +++ b/tests/dGameTests/dComponentsTests/ReplicaConstructionTests.cpp @@ -19,6 +19,7 @@ #include "InventoryComponent.h" #include "ItemComponent.h" #include "LevelProgressionComponent.h" +#include "LUPExhibitComponent.h" #include "PlayerForcedMovementComponent.h" #include "Item.h" #include "ModelComponent.h" @@ -370,6 +371,27 @@ TEST_F(ReplicaConstructionTest, AConstructionKeepsPendingLevelAndForcedMovementC EXPECT_EQ(again.GetNumberOfBitsUsed(), 2u); } +// The client learns the exhibit's LOT only from the component's block (LWOLUPExhibitComponent::Deserialize: a flag +// and the LOT). DLU wrote it on a construction only while it was dirty, so a player who came into range after the +// first update saw no exhibit until the next one was picked. +TEST_F(ReplicaConstructionTest, LupExhibitConstructionAlwaysCarriesTheExhibit) { + Entity exhibit(1009, info); + auto* const component = exhibit.AddComponent(-1); + + RakNet::BitStream update; + component->Serialize(update, false); + RakNet::BitStream idle; + component->Serialize(idle, false); + EXPECT_EQ(idle.GetNumberOfBitsUsed(), 1u); + + RakNet::BitStream construction; + component->Serialize(construction, true); + RakNet::BitStream expected; + expected.Write1(); + expected.Write(11121); + ExpectSameBits(construction, expected); +} + // 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) {